I have a value sheet of type (x, y) and I would like to get an x sheet, but something goes wrong, here is the code:
x_list:: [(Double, Double)] -> [Double]
x_list list = Prelude.foldl(\t xl -> (fst t):xl) list []
I get this error:
• Couldn't match expected type: (Double, b0)
with actual type: [Double]
• In the first argument of ‘fst’, namely ‘t’
In the first argument of ‘(:)’, namely ‘(fst t)’
In the expression: (fst t) : xl
CodePudding user response:
There are a couple of problems in your code, both related to argument order:
foldl, like all the other folds, takes the argument list as its last (3rd) argument and the starting accumulator (your []
) as the one before that - so you need to switch over the list
and []
in your definition.
Similarly, the fold function itself has type b -> a -> b
- that is it takes the old accumulator as its first element and the element of the list you're folding as its second. So in your case the first argument is a list of doubles and the second is a pair of doubles (not a list) - your implementation and variable names clearly imply you thought it was the other way round, but the compiler can't accept this.
(Note that for a right fold the argument order is reversed. This can be confusing - I always remember it by mentally placing the current accumulator at one end of the list: the left end for a left fold and the right end for a right fold, and then noting the fold function consumes its arguments in left-to-right order. Don't worry if this isn't helpful for you - I've probably explained it badly anyway. It's not essential, but it helps me!)
So your function when fixed in the above 2 ways will look like this:
x_list:: [(Double, Double)] -> [Double]
x_list list = Prelude.foldl(\xl t -> (fst t):xl) [] list
Note finally that this is much more simply and readably expressed with the map
function - which (as you are doing here) applies a function to every element of a list. In this case the simplest definition would be
x_list list = map fst list
or, by "eta reduction", just:
x_list = map fst
CodePudding user response:
I think what you are looking for is map
(https://hackage.haskell.org/package/base-4.17.0.0/docs/Prelude.html#v:map)
This takes a list and applies a given function to each element
xList :: [(Double,Double)] -> [Double]
xList = map fst
or a bit more explicit
xList' :: [(Double,Double)] -> [Double]
xList' list = map (\(x,y) -> x) list
Loading this into GHCi would give you
ghci> xList' [(1,2),(3,4)]
[1.0,3.0]
CodePudding user response:
The easiest way is to work with a map
:
x_list :: [(a, b)] -> [a]
x_list = map fst
you can also let this work for foldr
with:
x_list :: [(a, b)] -> [a]
x_list list = foldr (\(t, _) xl -> t:xl) [] list
or with foldl
, but this will work in quadratic time, and only produce a result when enumerated over all elements:
x_list :: [(a, b)] -> [a]
x_list list = foldl (\xl (t, _) -> xl [t]) [] list