为什么让y = 1 + y编译,这是什么意思?

时间:2014-12-18 23:15:59

标签: haskell

在GHCi中let y = y + 1编译得很好,但是当我尝试评估时,我得到了*** Exception: <<loop>>

为什么没有编译错误,它是什么意思<<loop>>

2 个答案:

答案 0 :(得分:25)

Haskell letwhere和顶级绑定默认递归,即使它们不是函数。因此let y = y + 1定义了向数字添加1的无限循环。 GHC用<<loop>>异常表示这样的循环 - 当然它可以捕获它们!

这可用于延迟操作,因为它允许我们轻松定义诸如无限列表(let xs = 0:xs)之类的东西,这些列表定义明确且对普通代码实际上很有用。但是,它不适用于+等严格操作(对于大多数数字类型),因为它们需要立即评估整个(无限)事物。

答案 1 :(得分:0)

我想添加一个可能实际有用的最小示例。

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

在这种情况下,y是无穷大,直到同构。 (尽管我的fromInteger显然是一个糟糕的实现,因此将文字1更改为其他内容而不修复fromInteger将会失败。)

请注意,这只有效,因为我定义的(+)在其第一个参数中是懒惰的,而我定义的compare也是懒惰的。< / p>