Reputation: 85
Im trying to implement a function that can flatten a list of lists. only one layer deep. so if I called flatten [[3],[3, 5]]
I would get [3,3,5]. this is my code:
flatten :: [[a]] -> [a]
flatten [[]] = []
flatten [(x:xs)] =
flatten [xs] ++ [x]
I am getting an error "non exhaustive patterns in function flatten" when I call flatten [[3], [5]]
Upvotes: 3
Views: 8142
Reputation: 6111
You can implement it exactly the same way concat is implemented in Prelude:
flatten :: [[a]] -> [a]
flatten xs = foldr (++) [] xs
Upvotes: 0
Reputation: 8866
Possible solution:
flatten [] = []
flatten ([]:vs) = flatten vs
flatten ((x:xs):vs) = x:flatten (xs:vs)
Upvotes: 3
Reputation: 89073
There are two fundamental patterns to consider when processing a list. Any list must be either:
[]
)_:_
)Since concat acts upon a list-of-lists, we can break that second case down into two cases by pattern matching on the first element of the list, which must be either
[]:_
)(_:_):_
)1Which gives us three patterns all together:
concat [] = ...
concat ([]:xss) = ...
concat ((x:xs):xss) = ...
See how every list-of-lists must match exactly one of those patterns?
Now, given that breakdown, see if you can implement concat
only using x
, xs
, xss
, :
, []
, and concat
itself.
(_:_):_
is a different pattern from _:_:_
, which is more explictly written _:(_:_)
. The former is a pattern for a non-empty list at the head of a list of lists. The latter is a pattern for a list of at least two elements.Upvotes: 10
Reputation: 444
You are using incorrect patterns.
[smth]
matches list with one element, in your case:
[[]]
- is list with one empty list
[(x:xs)]
- is list with one element - list (x:xs)
, which is not empty
So both cases matches single-element list. That's why function fails on [[3], [5]]
Obviously, you may wanted other two cases: empty ([]
) and not empty list ((x:xs)
)
flatten :: [[a]] -> [a]
flatten [] = []
flatten (x:xs)
Upvotes: 0