2

I know about the length function, but if I have a list such as [(1,2),(2,3),(3,4)] and try to use length it does not work. I tried to concatenate but that doesn't help. Any idea how?

duplode
  • 33,731
  • 7
  • 79
  • 150
F.A
  • 297
  • 1
  • 3
  • 13
  • 1
    Obliously it's `(*2) . length`, because every element is a 2-tuple. (Hint: Haskell is very unlike Python or JS with regard to data structures.) – 9000 Nov 09 '15 at 00:21
  • 2
    Obviously length is 3 and every element is a tuple - if you look for a function 'concatMap' and convert the tuples into lists (note: that then these tuples need to be homogeneous) with a helper function you might get the answer 6 – epsilonhalbe Nov 09 '15 at 00:27
  • 3
    Does not work is **not** a problem description. If you get an error please post 1) a minimal code that we can use to reproduce the error and 2) the full error message. If the result you obtain isn't what you intended you have to provide 1) the result you've got and 2) the result you expected along with the input you used. – Bakuriu Nov 09 '15 at 12:08

2 Answers2

6

While the sensible solution to your immediate problem is (2 *) . length, as 9000 pointed out, it is worth dwelling a bit on why length [(1,2),(2,3),(3,4)] doesn't do what you expect. A Haskell list contains an arbitrary number of elements of the same type. A Haskell pair, however, has exactly two elements of possibly different types, which is something quite different and which is not implicitly converted into a list (see this question for further discussion of that point). However, nothing stops us from writing a conversion function ourselves:

pairToList :: (a, a) -> [a]
pairToList (x, y) = [x, y]

Note that the argument of pairToList is of type (a, a); that is, the function only accepts pairs with both elements having the same type.

Given pairToList, we can convert the pairs in your list...

GHCi> map pairToList [(1,2),(2,3),(3,4)]
[[1,2],[2,3],[3,4]]

... and then proceed as you planned originally:

GHCi> (length . concat . map pairToList) [(1,2),(2,3),(3,4)]
6

The concatMap function combines map and concat into a single pass...

GHCi> :t concatMap
concatMap :: Foldable t => (a -> [b]) -> t a -> [b]

... and so your function becomes simply:

GHCi> (length . concatMap pairToList) [(1,2),(2,3),(3,4)]
6
Community
  • 1
  • 1
duplode
  • 33,731
  • 7
  • 79
  • 150
  • 1
    I would insist that the `length . concatMap pairToList ` solution is strictly inferior to the `(*2) . length` solution, and should be rejected in favor of the latter. The thing is that with `[(a, a)]`, just knowing the *type* guarantees that each element of the list is a pair that has two elements. The `(*2) . length` solution exploits this guarantee, whereas `length . concatMap pairToList ` doesn't. – Luis Casillas Nov 10 '15 at 01:24
  • @LuisCasillas I rephrased the opening sentence to make that clearer (the rest of the answer is more of a digression to clarify the confusion implicit in the question). – duplode Nov 11 '15 at 02:06
4

length [(1,2),(2,3),(3,4)] gives you 3 because there are precisely three elements in the list where the elements are tuples, each consisting of two integers. use this function to get all the "elements"

tupleLength :: [(Int, Int)] -> Int
tupleLength = (*2) . length
nburk
  • 22,409
  • 18
  • 87
  • 132
  • 1
    I'm nit-picking here, but `pairListLength` would be a better name; the term "tuple" is too general. – jub0bs Nov 09 '15 at 09:52