I was looking into this solution from GitHub for a problem asked in Haskell from First Principles book. Here is the code
data Nat =
Zero
| Succ Nat deriving (Eq, Show)
integerToNat :: Integer -> Maybe Nat
integerToNat i
| i < 0 = Nothing
| i == 0 = Just Zero
| i > 0 = Just (Succ x) where (Just x) = integerToNat $ i-1
I'm confused at
where (Just x) = integerToNat $ i-1
I thought I can only assign an expression to an identifier in where. But it looks like the (Just x) unpacks the value of the expression assigned and assigns x back to (Succ x).
Can somebody explain why this works?
The Haskell context free syntax, has an entry about the right hand side (rhs) of a function:
rhs →
=exp [wheredecls]
| gdrhs [wheredecls]
So that mean we have to take a look to decls to get the where syntax. decls is a sequence of decls:
decls → { decl1; ...; decln }
And a decl has again two possible rules:
decl→ gendecl
| (funlhs | pat) rhs
So that means we can declare patterns (pat) in the left hand side of a where clause. Actually in a where a = 1, a is already a pattern so to speak. The pattern consists out of one variable. But constructors, alias operators, etc. are all acceptable at the left hand side of a where clause.
A pattern can be a variable, a generic constructor, a qualified constructor, a literatal, a wildcard, list pattern, tuple pattern, irrefutable pattern, etc. Then entire grammar for patterns can be found here. So in short it works like pattern matching in the head of the function.
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