Home > database >  How do I get a value list from a tuple list?
How do I get a value list from a tuple list?

Time:12-19

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
  • Related