【发布时间】:2016-10-12 05:04:09
【问题描述】:
我最近遇到了“提升的产品类型”一词,与未提升的产品类型形成对比。
我不记得上下文,但我看到 Stack Overflow 上还有其他问题询问未提升产品类型的缺点 (example)。
我或多或少知道什么是产品类型。它类似于(a, b) 或Foo a b c,大致对应于集合论中的笛卡尔积。
在这种情况下,术语“已提升”和“未提升”是什么意思?
【问题讨论】:
我最近遇到了“提升的产品类型”一词,与未提升的产品类型形成对比。
我不记得上下文,但我看到 Stack Overflow 上还有其他问题询问未提升产品类型的缺点 (example)。
我或多或少知道什么是产品类型。它类似于(a, b) 或Foo a b c,大致对应于集合论中的笛卡尔积。
在这种情况下,术语“已提升”和“未提升”是什么意思?
【问题讨论】:
来自GHC docs:
“提升”类型意味着该类型的术语可能是底部。
“盒装”类型意味着一个值由指向堆对象的指针表示。
一些影响包括:
id 0 :: Int# 这样的东西不起作用。查看this answer,了解您如何(自 GHC 8.0 起)有时可以解决此问题。请注意,您可以使用 MagicHash 和 UnboxedTuples 扩展在 GHC 中创建未提升的产品(尽管我认为它们不能很好地与 GHCi 配合使用):
{-# LANGUAGE MagicHash, UnboxedTuples #-}
extGCD :: Int -> Int -> (# Int, Int, Int #)
extGCD a 0 = (# 1, 0, a #)
extGCD a b = let (q, r) = a `quotRem` b
(# s, t, g #) = extGCD b r
in (# t, s - q * t, abs g #)
除了这个扩展之外,我相信你会发现唯一未提升的类型在GHC.Exts 中并且是原始类型。有一些讨论允许将自定义未提升数据类型集成到 GHC here。
最后一句话:提升类型有种类*,未提升类型有种类#。 This answer 对 cmets 中链接的问题进行了更详细的说明。
【讨论】:
*,除非另有说明。下面的链接实际上显示了如何使用 GHC 8.0 的更新的 levity 多态性功能来解除此限制。这说明清楚了吗?
forall (k :: RuntimeRep) (t :: TYPE k) :)
来自 GHC documentation:
Lifted
A type is lifted iff it has bottom as an element.
提升类型的值可以是bottom。也就是说,它可以是undefined,或者可能是一个永远不会完成的计算,或者一个抛出异常的计算。
同时,未提升的类型没有那些潜在的麻烦的额外值。这在纯粹的“语义”级别中很有用(如果您不想要那些额外的值),它还可以通过减少代价高昂的间接调用来促进更有效的实现。名为the worker-wrapper transformation 的 GHC 优化利用了这一点(请参阅链接论文的第 5.1 节)。
已提升和未提升的类型有不同的种类。提升的类型位于*,未提升的类型位于#。
目前,GHC 不允许您轻松定义自己的复杂未提升数据类型。但是有proposals 允许这样做。
【讨论】: