I'm trying to make a function in haskell to know if all the elements in a list of list have the same length. (I've search answers in previous posts but none of them works).
sameLength :: [[t]] -> String
sameLength [] = "Empty list"
sameLength [[items]]
| and $ map (\x -> length x == (length $ head [[items]])) [[items]] = "Same length"
| otherwise = "Not the same length"
The problem is that it doesn't work :
*Main> :l test.hs
[1 of 1] Compiling Main ( test.hs, interpreted )
Ok, modules loaded: Main.
*Main> sameLength []
"Empty list"
*Main> sameLength [[1,2],[3,4]]
"*** Exception: test.hs:(2,1)-(5,39): Non-exhaustive patterns in function sameLength
*Main> sameLength [[1,2]]
"*** Exception: test.hs:(2,1)-(5,39): Non-exhaustive patterns in function sameLength
I don't really see where is the problem. It treat the case in which the parameter is an empty list and in which it is not. Am I wrong ? Did i miss something ?
Thanks for your help :)
you have too many [..]
in here:
sameLength [[items]]
(as Silvio explained really well) - try
sameLength items
instead.
Further as a == a
, you don't have to check if the length of the head is the same as the length of the head` (of course) and so I would recommend doing something like this:
sameLength :: [[a]] -> Bool
sameLength [] = True
sameLength (h:tl) = all ((length h ==) . length) tl
as I think the Bool
result is just more useful and natural
all
takes a predicate and a list and checks if the predicate holds for each element of the list - so (length h ==) . length = \xs -> length h == length xs
as a predicate checks if a given list xs
has the same length as the head-list h
- so due to the remark above you only have to check this with the tail-list tl
You can argue if all elements of the empty list should have the same length - but I think the answer should be yes ;)
Prelude> sameLength [[1,2],[3,4]]
True
Prelude> sameLength [[1,2],[3,4,5]]
False
Prelude> sameLength [[1,2]]
True
Prelude> sameLength []
True
(or you do not like the point-free style)
sameLength :: [[a]] -> Bool
sameLength [] = True
sameLength (h:tl) = let l = length h
in all (\xs -> length xs == l) tl