Reputation: 2066
So I have a custom data type, let's call it Struct
, defined like this:
data Struct = Struct [SubStruct] deriving (Read, Show)
data SubStruct = SubStruct (Int, Int) deriving (Read, Show)
What I need to do is to go through all the elements in Struct
and find the minimum based onfst
and then based on the snd
. How do I do that?
More specifically, I want to get another SubStruct
such as:
SubStruct (-2,-5)
, based on the example in the code.
Currently, i started by doing this:
import Data.List
import Data.Function (on)
import Data.List (sortBy)
data Struct = Struct [SubStruct] deriving (Read, Show)
data SubStruct = SubStruct (Int, Int) deriving (Read, Show )
struct s sx = Struct(s:sx)
subStruct :: (Int, Int) -> SubStruct
subStruct (x, y) = SubStruct (x, y)
substructs = Struct $ [subStruct (0,1), subStruct (-2, 3), subStruct (4,-5)]
results xs = sortBy (compare `on` fst) (substructs xs)
But I get this error:
Couldn't match expected type `t -> [(a, b)]'
with actual type `Struct'
Relevant bindings include
xs :: t (bound at bbox.hs:15:9)
results :: t -> [(a, b)] (bound at file.hs:15:1)
The function `substructs' is applied to one argument,
but its type `Struct' has none
In the second argument of `sortBy', namely `(substructs xs)'
In the expression: sortBy (compare `on` fst) (substructs xs)
Upvotes: 1
Views: 851
Reputation: 23920
Why not use the unzip
function. If we define an auxiliary function:
unSubStruct :: SubStruct -> (Int, Int)
unSubStruct (SubStruct p) = p
Then the function that returns the element that you want can be written as:
getMin :: Struct -> SubStruct
getMin (Struct l) = SubStruct (minimum xs, minimum ys)
where
(xs, ys) = unzip $ map unSubStruct l
Note that this will traverse the list twice. You can avoid that if you define your own version minimum
that works on pairs:
getMin :: Struct -> SubStruct
getMin (Struct l) =
SubStruct $ foldr1 minPair $ map unSubStruct l
where
minPair (x0, y0) (x, y) = (min x0 x, min y0 y)
Upvotes: 6
Reputation: 36339
You have a list of SubStruct
, which is basically the same as a list of tuples.
So, one solution using only common functions would be:
result = SubStruct (min1, min2) where
min1 = minimum (map fst . list)
min2 = minimum (map snd . list)
list = case substructs of
Struct this -> map (\(SubStruct t) -> t) this
Upvotes: 0