seq force如何运作?

acf*_*zer 26 evaluation haskell lazy-evaluation semantics

背景

这个问题源于一个挑战布伦特Yorgey提出在OPLSS:写一个函数f :: (Int -> Int) -> Bool区分f undefinedf (\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也是如此.所有有用的东西.


Vic*_*rov 9

如何制作快速咖喱有一个更高层次的STG机器描述:推/输入与评估/应用

图2包含适用于函数的规则CASEANY.在本文中,"是一种价值"命题意味着:

  • 它是一个饱和的构造函数应用程序
  • 这是一个功能
  • 它是一个部分函数应用程序(它仍然是一个函数,语义上)

未装箱的值(包括文字)会被特别处理,更多信息可以在未装箱的值中找到, 作为头等公民

所有这些都是实现细节,隐藏在编译器(GHC)中.Haskell的case表达式并没有强制它的监督,只有模式匹配和seq这样做.