【问题标题】:Type of primitive functions in lazy evaluation惰性求值中的原始函数类型
【发布时间】:2017-01-08 09:17:06
【问题描述】:

我想知道 Haskell 等惰性函数式编程语言中原始函数的确切类型是什么。

假设 thunk 被评估为弱头范式的对象。那么,像 C 这样的严格语言中的原始函数应该是什么类型呢?

我的猜测是:

primitive1 : (thunk, thunk, ...) -> thunk
primitive2 : (thunk, thunk, ...) -> object

我认为原始函数应该作为参数传递 thunk,因为它们可能不需要其中的一些。但是,我不知道他们是否应该返回一个 thunk 或评估对象,而后者必须用下面这样的函数包装以使其变得惰性。

lazy : ((thunk, thunk, ...) -> object) -> ((thunk, thunk, ...) -> thunk)

【问题讨论】:

  • 嗯,这个问题没有唯一的答案,因为它取决于实现。在 ghc 中,原始操作具有原始类型,即与 C 中的类型相同。您可以在 thunk 中包装和展开原始类型的单独操作。
  • @augustss if 和 case 表达式怎么样?我猜他们的原语必须直接传递 thunk。或者,它们是咖喱的吗?
  • 一个 if 表达式被翻译成一个 case 表达式。并且没有用于 case 的原语,它被翻译成取决于类型的(抽象)机器代码。简化后,首先将检查对象评估为 WHNF,然后提取其构造函数编号并将其用作跳转表中的偏移量。您跳转到的代码将解包构造函数的字段并继续进行评估。

标签: c haskell functional-programming lazy-evaluation


【解决方案1】:

在 GHC 中,Haskell 原始函数(有时称为 PrimOp)是 使用混合指针(指向“堆对象”)调用并取消装箱 类型(包括 C 风格的整数、双精度等)。 Haskell 类型系统 确保 PrimOps 始终获取 他们期望的指针和未装箱的值。这一点很重要 但要注意,原语期望指向特定类型堆对象的指针,例如String, 它期望一个指向堆对象的指针,该对象可能或者是一个列表 构造函数(因为 Haskell String 是字符列表)或 thunk 可以评估为列表构造函数。

因此,Haskell PrimOp 的“严格”类型没有区别 在重击和非重击之间。如果有一个原始函数 获取列表的长度,例如(没有),使用您的符号,它可能具有以下类型:

primitiveLength : (list_object) -> unboxed_int

list_object 是指向任一列表的指针 构造函数或可以产生列表构造函数的thunk。

这确实是唯一明智的方法。 PrimOp 无法控制它的参数是否仍然是一个 thunk 或已经部分(或全部!)由一些先前的计算评估,因此它必须准备好接受任何一个。

类似地,如果 Haskell PrimOp 返回一个堆对象,从技术上讲,该对象可以是 thunk 或非 thunk,并且选择不会影响原语的“严格”类型签名。

实际上,PrimOp 返回 thunk 并不是很有用。在惰性语言中,调用原语的事实意味着需要它的返回值。如果它返回一个 thunk,则需要立即评估该 thunk,那么为什么要返回一个 thunk?

(已编辑添加:)顺便说一句,上面的 PrimOps 并没有什么特别之处:用户定义的 Haskell 函数也使用指针和未装箱类型的混合调用(而且它们从不返回 thunk)。

【讨论】:

  • 原始函数中是否允许创建和评估 thunk?
  • 基元可以评估thunk,但很少有人这样做。例如,newArray# 可以采用 thunk(作为数组元素的初始值),但它不评估它——它只是用指向 thunk 的指针填充数组。我猜raise# 是一个接受(并评估)thunk 的原语示例。由于评估 thunk 可以创建新的 thunk,这意味着 raise# 也能够隐式创建 thunk。我不知道显式创建 thunk 的原语,但我不明白为什么不能,因为原语可以创建堆对象,而 thunk 只是另一个堆对象。
  • @raviqqe,一个可以创建 thunk 的 primop 是 tryTakeMVar# :: MVar# s a -> State# s -> (#State# s, Int#, a#)。如果MVar 为空,它会返回一个未定义的值(如果强制会产生错误的thunk)。 tryReadMVar# 也是如此。它没有记录在案,但如果有人试图取消引用其密钥已被收集的弱指针,deRefWeak# 似乎也是如此。
猜你喜欢
  • 2021-01-13
  • 2011-11-03
  • 2017-05-12
  • 1970-01-01
  • 1970-01-01
  • 2018-10-08
  • 1970-01-01
  • 1970-01-01
  • 2020-06-24
相关资源
最近更新 更多