Why does let y = 1 + y compile, and what does it mean?

≯℡__Kan透↙ 提交于 2020-01-14 07:08:31

问题


In GHCi let y = y + 1 compiles fine, but when I try to evaluate y I got *** Exception: <<loop>>

Why is there no compile error and what does it mean <<loop>>?


回答1:


Haskell let, where and top-level bindings are recursive by default, even if they're not for a function. So let y = y + 1 defines an infinite loop of adding 1 to a number. GHC represents loops like this with the <<loop>> exception—if it can catch them, of course!

This is usable for lazy operations, because it allows us to easily define things like infinite lists (let xs = 0:xs), which are well-defined and actually useful for normal code. However, it can't work for strict operations like + (for most numeric types) because they require evaluating the whole (infinite) thing right away.




回答2:


I wanted to add a minimal example of where this might actually be useful.

data Peano = Z | S Peano

instance Num Peano where
    p + Z     = p
    p + (S q) = S (p + q)
    fromInteger 1 = S Z

instance Eq Peano where
    Z     == Z     = True
    Z     == _     = False
    _     == Z     = False
    (S p) == (S q) = p == q

instance Ord Peano where
    Z     `compare` Z     = EQ
    Z     `compare` _     = LT
    _     `compare` Z     = GT
    (S p) `compare` (S q) = p `compare` q

y :: Peano
y = y + 1

main :: IO ()
main = print $ 1 < y

In this case, y is infinity, up to isomorphism. (Though, my fromInteger is clearly a poor implementation, so changing either literal 1 to something else without fixing fromInteger will fail.)

Note that this only works because the (+) I've defined is lazy in it's first argument and the compare I've defined is also sufficiently lazy.



来源:https://stackoverflow.com/questions/27557380/why-does-let-y-1-y-compile-and-what-does-it-mean

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!