【问题标题】:What is the DataKinds extension of Haskell?Haskell 的 DataKinds 扩展是什么?
【发布时间】:2013-12-31 18:11:53
【问题描述】:

我试图找到对 DataKinds 扩展的解释,这对我来说是有意义的,因为我只阅读了Learn You a Haskell。有没有一个标准的资源对我来说是有意义的?

编辑:例如documentation

使用 -XDataKinds,GHC 会自动提升每个合适的数据类型 是一种类型,它的(值)构造函数是类型构造函数。 以下类型

并举例说明

data Nat = Ze | Su Nat

产生以下种类和类型构造函数:

Nat :: BOX
Ze :: Nat
Su :: Nat -> Nat

我不明白这一点。虽然我不明白 BOX 是什么意思,但声明 Ze :: NatSu :: Nat -> Nat 似乎说明了 Ze 和 Su 是正常的数据构造函数的情况,正如您期望在 ghci 中看到的那样

Prelude> :t Su
Su :: Nat -> Nat

【问题讨论】:

    标签: haskell types algebraic-data-types data-kinds


    【解决方案1】:

    让我们从基础开始

    种类

    种类是类型*的类型,例如

    Int :: *
    Bool :: *
    Maybe :: * -> *
    

    请注意,-> 也被重载为类型级别的“功能”。所以* 是一种普通的 Haskell 类型。

    我们可以要求 GHCi 打印带有:k 的东西。

    数据种类

    现在这不是很有用,因为我们无法制作自己的种类!用DataKinds,我们写的时候

     data Nat = S Nat | Z
    

    GHC 将为此创建相应的Nat

     Prelude> :k S
     S :: Nat -> Nat
     Prelude> :k Z
     Z :: Nat
    

    所以DataKinds 使 kind 系统可扩展。

    用途

    让我们使用 GADT 来做原型种类示例

     data Vec :: Nat -> * where
        Nil  :: Vec Z
        Cons :: Int -> Vec n -> Vec (S n)
    

    现在我们看到我们的Vec 类型是按长度索引的。

    这是基本的 10k 英尺概览。

    * 这实际上还在继续,Values : Types : Kinds : Sorts ... 一些语言(Coq、Agda ..)支持这种无限的宇宙堆栈,但 Haskell 将所有内容归为一类。

    【讨论】:

    • 这是否意味着表达式 S :: Nat -> Nat 被重载,因为它可以将 S 作为数据构造函数引用 NatS 作为类型构造函数类似Nat 的论点?您的 data Vec :: Nat -> * 示例是否应该改为 data Vec a :: Nat -> * 以反映 Vec 采用类型参数?
    • @user782220 1. 是 2. 不,我特意把Vec 做成单态的,如果你愿意也可以
    • 我认为在这一切中最容易忽略的是,没有 DataKinds,SZ 不是类型,而只是产生类型 Nat 的类型构造函数。对于 DataKinds,它们是类型,其类型是 Nat。它们之前不是类型的事实意味着以前它们不能在类型签名中被引用,这就是这一切的意义所在。
    • @Jules,该评论应该是一个答案!通常,当我看到使用 -XDataKinds 时,这是因为函数签名中需要构造函数(或者相反,当您想知道如何将构造函数放入函数签名中时,-XDataKinds 就是答案)
    • "SZ 不是类型,而只是产生 Nat 类型的类型构造函数应该是产生 Nat 类型数据的数据构造函数
    【解决方案2】:

    这是我的看法:

    考虑一个长度索引的向量类型:

    data Vec n a where
      Vnil  :: Vec Zero a
      Vcons :: a -> Vec n a -> Vec (Succ n) a
    
    data Zero
    data Succ a
    

    这里我们有一个 Kind Vec :: * -> * -> *。由于您可以通过以下方式表示零长度的 Int 向量:

    Vect Zero Int
    

    你也可以声明无意义的类型说:

    Vect Bool Int
    

    这意味着我们可以在类型级别进行无类型函数式编程。因此,我们通过引入数据类型来消除这种歧义,并且可以拥有这样的一种:

    Vec :: Nat -> * -> *
    

    所以现在我们的Vec 获得了一个名为Nat 的DataKind,我们可以将其声明为:

    datakind Nat = Zero | Succ Nat
    

    通过引入一种新的数据类型,没有人可以声明无意义的类型,因为 Vec 现在具有更受约束的类型签名。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-20
    • 2010-09-29
    • 2013-06-19
    • 2020-03-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多