什么是Levity多态性


80

正如问题的标题所示,我想知道什么是Levity多态性,其动机是什么?我知道此页面中包含一些详细信息,但其中的大多数解释都超出了我的头脑。:)

尽管此页面友好一些,但我仍然无法理解其背后的动机。

Answers:


80

注意:此答案基于有关Levity讨论的最新观察结果。有关Levity多态性的所有内容目前仅在GHC 8.0版本候选版本中实现,因此可能会发生变化(例如,参见#11471)。


TL; DR:这是一种使函数在提升和未提升类型上多态的方法,而常规函数则无法实现。例如,下面的代码由于Int#具有kind #,所以没有使用常规多态进行类型检查,但是其中的类型变量id具有kind *

{-# LANGUAGE MagicHash #-}

import GHC.Prim

example :: Int# -> Int# 
example = id            -- does not work, since id :: a -> a
Couldn't match kind ‘*’ with ‘#’
When matching types
  a0 :: *
  Int# :: #
Expected type: Int# -> Int#
  Actual type: a0 -> a0
In the expression: id

注意,(->)仍然使用一些魔术。


在我开始回答这个问题之前,让我们退后一步,转到最常用的功能之一($)

什么是($)类型?嗯,根据Hackage和报告,

($) :: (a -> b) -> a -> b

但是,这还不是100%完成。这是一个方便的小谎言。问题在于多态类型(如ab)具有种类*。但是,(库)开发人员($)不仅希望将其用于具有kind的类型*,还希望将其用于kind的类型#,例如

unwrapInt :: Int -> Int#

虽然Int有善良*(可以是底部),但Int#有善良#(根本不能是底部)。仍然,以下代码类型检查:

unwrapInt $ 42

那不行 还记得返回类型($)吗?它是多态的,而多态类型却是善良的*,不是#!那为什么行得通呢?首先,它是一个bug,然后是一个黑客(ghc-dev邮件列表中Ryan Scott的邮件摘录):

那么为什么会这样呢?

长答案是,在GHC 8.0之前的类型签名中($) :: (a -> b) -> a -> bb实际上不是实物*,而是实物OpenKindOpenKind是一种可怕的骇客,它允许提升类型(kind *)和未提升类型(kind #)都居住,这就是类型检查的原因(unwrapInt $ 42)

那么($),GHC 8.0中的新类型是什么?它的

($) :: forall (w :: Levity) a (b :: TYPE w). (a -> b) -> a -> b
-- will likely change according to Richard E.

要了解它,我们必须查看Levity

data Levity = Lifted | Unlifted

现在,我们可以认为($)具有以下两种类型之一,因为只有两种选择w

-- pseudo types
($) :: forall a (b :: TYPE   Lifted). (a -> b) -> a -> b
($) :: forall a (b :: TYPE Unlifted). (a -> b) -> a -> b

TYPE是一个神奇的常数,它重新定义了种*#作为

type * = TYPE Lifted
type # = TYPE Unlifted

对种类的量化也相当新,并且是Haskell中依赖类型集成的一部分。

Levity多态性的名称来自于以下事实:您现在可以在提升类型和未提升类型上编写多态函数,而以前的多态性限制是不允许/可能的。同时也摆脱了OpenKind黑客攻击。关于这两种处理,这确实是“正当的”。

顺便说一句,您并不孤单。甚至西蒙·佩顿·琼斯(Simon Peyton Jones)都说有必要创建一个Levity Wiki页面,而Richard E.(当前的实现者)表示,该Wiki页面需要对当前过程进行更新

参考文献


3
“处理两种” :)
Sibi

4
嗯 我想我更喜欢将这些东西隐藏起来的丑陋的骇客。
jberryman '16

3
为什么不这样($) :: forall (w1 w2 :: Levity) (a :: TYPE w1) (b :: TYPE w2). (a -> b) -> a -> b,即为什么($)不应该将其与带有未修饰参数的函数一起使用?
仙人掌

3
@bug中讨论过的仙人掌,请参阅SPJ的评论:ghc.haskell.org/trac/ghc/ticket/8739#comment
Zeta,

1
@jberryman:#11549将隐藏RuntimeRep(替换Levity)。
Zeta '02
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.