我刚刚读完了轻松多态这篇论文。
我有一个问题,就是为什么当使用undefined
作为非装箱类型时,它可以是轻松多态的。
首先,让我们从论文中一些关于装箱性的定义开始:
boxed:
指针指向堆中的值表示boxed值。
Int
和Bool
是具有boxed值的类型的示例。
unboxed:
接下来的论文介绍了一些levity的定义:
lifted:
一个lifted类型是指它是惰性的。
一个lifted类型有一个额外的元素,超出了正常元素的范畴,表示一个非终止计算。
例如,类型
Bool
是lifted的,这意味着Bool
有三个不同的值:True
、False
和⊥
(底部)。所有lifted类型都必须boxed。
unlifted
一个unlifted类型是指它是严格的。
元素
⊥
在unlifted类型中不存在。Int#
和Char#
是unlifted类型的例子。
该论文还解释了GHC 8提供的功能,允许类型变量具有多态的levity。
这使您可以编写以下类型的levity-polymorphic undefined
:
undefined :: forall (r :: RuntimeRep). forall (a :: TYPE r). a
这意味着undefined
应该适用于任何RuntimeRep
,甚至是未提升的类型。
以下是在GHCi中使用undefined
作为未装箱、未提升的Int#
的示例:
> :set -XMagicHash
> import GHC.Prim
> import GHC.Exts
> I# (undefined :: Int#)
*** Exception: Prelude.undefined
我一直认为undefined
与⊥
(底部)相同。然而,论文中说:"元素⊥
在未提升的类型中不存在。"
这是怎么回事?当作为未提升的类型时,undefined
实际上不是⊥
吗?我是否误解了论文(或boxity或levity)的某些内容?
undefined
抛出一个异常,在这方面是底部的。 - Daniel Wagner_
)永远不能被绑定到未lifted类型的底部值。如果给定f (x :: Int#) = ...
,那么如果我调用f undefined
,执行永远不会到达右侧。GHC 将在调用f
之前尝试评估undefined
。 - dfeuer