【发布时间】:2011-09-20 11:38:25
【问题描述】:
背景
这个问题源于 Brent Yorgey 在 OPLSS 提出的挑战:编写一个函数 f :: (Int -> Int) -> Bool,将 f undefined 与 f (\x -> undefined) 区分开来。我们所有的答案要么使用seq,要么使用类似爆炸模式的东西,将糖化为seq。例如:
f :: (Int -> Int) -> Bool
f g = g `seq` True
*Main> f undefined
*** Exception: Prelude.undefined
*Main> f (\x -> undefined)
True
e1 `seq` e2
用来脱糖成
case e1 of { _ -> e2 }
所以我尝试手动脱糖。没用:
f' g = case g of { _ -> True }
*Main> f' undefined
True
*Main> f' (\x -> undefined)
True
问题
这种行为是否取决于更复杂的seq 描述的at the end of the commentary,如果是,它是如何工作的?如果没有这些原语,可以编写这样的f 吗?
x `seq` e2 ==> case seq# x RW of (# x, _ #) -> e2 -- Note shadowing!
e1 `seq` e2 ==> case seq# x RW of (# _, _ #) -> e2
【问题讨论】:
-
GHC 的评论是在谈论对 Core 的脱糖,其中
case e of { ... }始终表示“评估 e”。 -
seq是一种语言原语。如果您将其从语言中删除,您将失去区分这两个功能的能力。有些人会对此感到高兴:-) -
@Mikhail, @luqui:这些不应该是答案吗?
-
不,米哈伊尔的评论是正确的评论,因为它更正了问题中的一个细节,而不是回答它。卢克的评论在很大程度上回答了这个问题,并且稍微详细说明一下会是一个很好的答案。
-
@camccann:我认为米哈伊尔的评论直接解决了提问者提出这个问题的困惑。
标签: haskell semantics lazy-evaluation evaluation