In (vanilla) GHCi 8.6.5 following function was prefectly valid:
f xs@ ~(x:xt) = xs
If I now do the same in 9.0.1 I get an error
Suffix occurrence of @. For an as-pattern, remove the leading whitespace.
Just removing the white space between @
and ~
doesn't seem to suffice, as then @~
would be interpreted as an operator, so the only valid variation I found was
f xs@(~(x:xt)) = xs
I'd like to know the following, for which I couldn't find answers in the change notes:
xs@(~(x:xt))
really the best way to write this pattern, or is there a preferred way over this?In a functional language, pattern matching involves checking an argument against different forms. A simple example involves recursively defined operations on lists. I will use OCaml to explain pattern matching since it's my functional language of choice, but the concepts are the same in F# and Haskell, AFAIK.
We use pattern matching in Haskell to simplify our codes by identifying specific types of expression. We can also use if-else as an alternative to pattern matching. Pattern matching can also be seen as a kind of dynamic polymorphism where, based on the parameter list, different methods can be executed.
Generally, a lazy pattern match is translated to calling corresponding record field accessors. The key difference between strict pattern match is that the strict pattern match requires to check for the pair constructor before g can be evaluated.
As far as I know, most regex engine is greedy by default. Add a question mark at the end of quantifier will enable lazy match. As @Andre S mentioned in comment. Greedy: Keep searching until condition is not satisfied.
'Greedy' means match longest possible string. 'Lazy' means match shortest possible string. For example, the greedy h.+l matches 'hell' in 'hello' but the lazy h.+?l matches 'hel'. Brilliant, so lazy will stop as soon as the condition l is satisfied, but greedy means it will stop only once the condition l is not satisfied any more?
If you want only the first match to be retrieved, use the search method instead. Greedy means it will consume your pattern until there are none of them left and it can look no further. Lazy will stop as soon as it will encounter the first pattern you requested.
The changes to the handling of ~ and @ in GHC 9.0 are described here. Quoting from the migration guide:
GHC 9.0 implements Proposal 229, which means that the !, ~, and @ characters are more sensitive to preceding and trailing whitespace than they were before. As a result, some things which used to parse one way will now parse differently (or throw a parse error).
Adding parentheses (variable@(~pattern)
) is a good solution. Alternatively, you could use a let
or where
binding, or a separate lazy case
:
rehead :: a -> [a] -> [a]
rehead x' xs0 = x' : xs
where
_x : xs = xs0
rehead :: a -> [a] -> [a]
rehead x' xs0 = let
_x : xs = xs0
in x' : xs
{-# Language PatternGuards #-}
rehead :: a -> [a] -> [a]
rehead x' xs0
| let _x : xs = xs0
= x' : xs
This can be very helpful if you want to use these bindings in subsequent guards.
rehead :: a -> [a] -> [a]
rehead x' xs0 = case xs0 of
~(_x : xs) -> x' : xs
All of these options are maximally lazy:
head (rehead 5 [1, 2])
head (rehead 5 [])
head (rehead 5 undefined)
5
If you’re using {-# Language Strict #-}
, then you must write the let
/where
bindings as ~(_x : xs) = xs0
to allow []
, and the list parameter binding as ~xs0
to allow undefined
; to get an irrefutable pattern (not just lazy) with case
, you must write ~(~(_x : xs))
.
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