Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pattern matching inside lambda

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)
like image 351
Daniel Avatar asked Jul 24 '16 12:07

Daniel


People also ask

What is pattern matching in OCaml?

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.

What is pattern matching in Haskell?

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.

Why ++ is not allowed in pattern matching?

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] .


1 Answers

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

  • input [1,2,3] = 1:[2,3] you get z=1 and zs=[2,3]
  • but when input [] 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.

like image 103
Random Dev Avatar answered Sep 27 '22 20:09

Random Dev