I'm learning Haskell. This is a trivial example but I'd like to understand the concept why I can't use the pattern matching inside the lambda function in the following example (i.e., why does the filterfold' function run but filterfold' gives a runtime error):
-- Runs
filterfold' :: (a -> Bool) -> [a] -> [a]
filterfold' p zs = foldr (\y zs -> if (p y) then y:zs else zs) [] zs
-- Runtime error: Non-exhaustive patterns in lambda
filterfold :: (a -> Bool) -> [a] -> [a]
filterfold p (z:zs) = foldr (\y (z:zs) -> if (p y) then y:(z:zs) else (z:zs)) [] (z:zs)
Pattern matching comes up in several places in OCaml: as a powerful control structure combining a multi-armed conditional, unification, data destructuring and variable binding; as a shortcut way of defining functions by case analysis; and as a way of handling exceptions.
Pattern matching consists of specifying patterns to which some data should conform and then checking to see if it does and deconstructing the data according to those patterns. When defining functions, you can define separate function bodies for different patterns.
You can only pattern-match on data constructors, and ++ is a function, not a data constructor. Data constructors are persistent; a value like 'c':[] cannot be simplified further, because it is a fundamental value of type [Char] .
you can use it but as the compiler tells you you are missing a case (when the input is []
)
See if you say z:zs
it will try to match this pattern with the input-list - if you
[1,2,3] = 1:[2,3]
you get z=1
and zs=[2,3]
[]
you cannot get a z
and zs
so that z:zs = []
(technically they are based on different constructors of the list-datatype)So at runtime it will not know how to handle this case/pattern when it sees []
and throw the exception.
if you look closely at your example you should see that you never actually use the parts anyway (meaning z
or zs
- you only use them as z:zs
again) so I cannot tell you how to do it better
anyway you can use the case
- expression inside of an lambda:
... = foldr (\ x zs -> case zs of
[] -> ...
z:zs -> ...
or you can use the LambdaCase extension to make it a bit shorter.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With