【问题标题】:How does seq force functions?seq force 是如何工作的?
【发布时间】:2011-09-20 11:38:25
【问题描述】:

背景

这个问题源于 Brent 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

GHC commentary on seq 这么说

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


【解决方案1】:

seq 无法在 Haskell 中实现。相反,它是在 Haskell 运行的任何运行时中对弱头范式进行评估的原始“钩子”。例如。在 GHC 上,它被编译为 GHC Core 中的 case,这会触发对最外层构造函数的评估。

由于无法在纯 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. }

由于函数没有正常形式,seq 一旦达到一个就停止计算。

编译器神奇地可用。其他原语也是如此,例如 parunsafeCoerceRealWorld 令牌、forkOn 等。所有有用的东西。

【讨论】:

  • 这是否意味着函数一旦到达核心就会被包装在数据构造函数中:“例如,在 GHC 上,它被编译为 GHC 核心中的case,这会触发对最外层构造函数的评估。”?我记得在研究 STG 机器时,case 可以检查代数类型或原语,所以我想这是有道理的。
  • 有点。它们在 STG 机器中表示为特定类型的闭包,FUN(和朋友)。 hackage.haskell.org/trac/ghc/wiki/Commentary/Rts/Storage/…
  • 我的困惑来自此文档:research.microsoft.com/apps/pubs/default.aspx?id=67083,其中操作语义指定了一种从 case 表达式返回饱和构造函数或未装箱原语的方法。返回函数没有规则,所以我想要么a)它们被包装在构造函数中,要么b)后来添加了这样的规则?
【解决方案2】:

How to make a fast curry: push/enter vs eval/apply中对STG-machine有更高级的描述

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

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

未装箱的值,包括字面量都经过特殊处理,更多信息可以在Unboxed values as first class citizens中找到

所有这些都是实现细节,隐藏在编译器 (GHC) 中。 Haskell 的 case 表达式不强制它的审查员,只有模式匹配和 seq 可以。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-23
    • 1970-01-01
    • 2014-01-30
    • 2018-09-15
    • 1970-01-01
    • 2017-12-25
    • 2019-01-07
    • 2017-01-31
    相关资源
    最近更新 更多