惰性评估中原始函数的类型
我想知道像Haskell这样的懒惰函数式编程语言中原始函数的确切类型是什么。
假设thunk被评估为弱头标准形式的对象。 那么,像C这样的严格语言中的原始函数应该是什么类型呢?
我的猜测是:
primitive1 : (thunk, thunk, ...) -> thunk
primitive2 : (thunk, thunk, ...) -> object
我认为原始函数应该通过thunk作为参数,因为它们可能不需要其中的一些。 但是,我不知道他们是否应该返回一个thunk或者被评估对象,而后者必须用下面的一些函数包装来使其变得懒惰。
lazy : ((thunk, thunk, ...) -> object) -> ((thunk, thunk, ...) -> thunk)
在GHC中,Haskell原始函数(有时称为PrimOp)是通过混合指针(“堆对象”)和非盒装类型(包括C风格整数,双精度等)来调用的。 Haskell类型系统确保PrimOps始终获取它们所期望的指针和取消装箱值的数量,顺序和类型。 然而,需要注意的是,如果一个原语需要一个指向特定类型堆对象的指针,比如一个String
,它需要一个指向堆对象的指针,该对象可以是一个列表构造函数(因为Haskell String
是字符列表) 或可以评估为列表构造函数的thunk。
因此,Haskell PrimOp的“严格”类型不区分thunk和non-thunk。 如果有一个原始函数来获取列表的长度,例如(没有),它可能会使用符号的类型:
primitiveLength : (list_object) -> unboxed_int
其中list_object
将是一个指针到任何一个列表构造器或一个thunk能够产生列表的构造方法。
这真的是唯一明智的做法。 一个PrimOp无法控制其参数是否仍然是一个thunk,或者已经部分(或完全)被一些先前的计算所评估,所以它必须准备好接受。
同样,如果一个Haskell PrimOp返回一个堆对象,那么该对象在技术上可能是thunk或非thunk,并且该选择对原语的“strict”类型签名没有影响。
在实践中,PrimOp返回thunk并不是非常有用。 在一种懒惰的语言中,原语被调用的事实意味着它需要返回值。 如果它返回一个thunk,那个thunk将需要立即进行评估,那么为什么要返回一个thunk?
(编辑添加:)顺便说一句,上面的PrimOps没有什么特别的:用户定义的Haskell函数也被称为指针和非盒装类型的混合(也不会返回thunk)。
链接地址: http://www.djcxy.com/p/42989.html