I have been having difficulty understanding why the haskell expression let (x,y) = (y,1) in (x,y)
converges to (1,1)
as expected but fix (\(x,y)-> (y,1))
results in <<loop>>
being thrown. Can anyone explain this?
Asked
Active
Viewed 314 times
17

Chris Martin
- 30,334
- 10
- 78
- 137

Alexander Wittmond
- 213
- 1
- 5
-
the fix expression is equivalent to `let g (x,y) = (y,1) ; r = g r in r`. – Will Ness Jan 10 '18 at 17:15
1 Answers
21
By default, the outermost patterns used in let
bindings are lazy. However, patterns used in lambda bindings are strict, so the pattern match against the tuple forces too much too early. You can explicitly write a lazy pattern match by prefixing it with ~
, making the lambda pattern equivalent to the let
pattern:
ghci> fix (\(~(x, y)) -> (y, 1))
(1,1)
This defers the actual evaluation of the pattern match until one of bound variables is forced, instead of when the function is called, avoiding the loop.
For more information, see the Haskell wiki article on lazy patterns.

Alexis King
- 43,109
- 15
- 131
- 205