acf*_*zer 26 evaluation haskell lazy-evaluation semantics
这个问题源于一个挑战布伦特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
Run Code Online (Sandbox Code Playgroud)
该GHC评上seq说,
e1 `seq` e2
Run Code Online (Sandbox Code Playgroud)
过去常见的
case e1 of { _ -> e2 }
Run Code Online (Sandbox Code Playgroud)
所以我尝试了手工制作.它不起作用:
f' g = case g of { _ -> True }
*Main> f' undefined
True
*Main> f' (\x -> undefined)
True
Run Code Online (Sandbox Code Playgroud)
这种行为是否取决于评论末尾seq描述的更复杂,如果是,它是如何工作的?这样的原语可以没有这些原语吗?f
x `seq` e2 ==> case seq# x RW of (# x, _ #) -> e2 -- Note shadowing!
e1 `seq` e2 ==> case seq# x RW of (# _, _ #) -> e2
Run Code Online (Sandbox Code Playgroud)
Don*_*art 23
seq无法在Haskell中实现.相反,它是在运行Haskell的任何运行时中对弱头正常形式进行求值的原始"钩子".例如,在GHC上,它被编译为caseGHC Core中的一个,它触发对最外层构造函数的评估.
由于它不能在纯Haskell中实现,因此它(在GHC中)被定义为一个primop:
pseudoop "seq"
a -> b -> b
{ Evaluates its first argument to head normal form, and then returns its second
argument as the result. }
Run Code Online (Sandbox Code Playgroud)
由于函数没有正常形式,seq一旦达到一个就停止评估.
神奇地可用于编译器.对于其他原语(如paror unsafeCoerce,RealWorld令牌等)forkOn也是如此.所有有用的东西.
如何制作快速咖喱有一个更高层次的STG机器描述:推/输入与评估/应用
图2包含适用于函数的规则CASEANY.在本文中,"是一种价值"命题意味着:
未装箱的值(包括文字)会被特别处理,更多信息可以在未装箱的值中找到, 作为头等公民
所有这些都是实现细节,隐藏在编译器(GHC)中.Haskell的case表达式并没有强制它的监督,只有模式匹配和seq这样做.