亲切的签名

Ext*_*ity 12 haskell types

我正在浏览Haskell维基书籍GADTS

https://en.wikibooks.org/wiki/Haskell/GADT指南.

我一直很好地跟踪,直到添加了一个Kind签名,它概括了Cons构造函数的约束类型.

data Safe
data NotSafe

data MarkedList             ::  * -> * -> * where
  Nil                       ::  MarkedList t NotSafe
  Cons                      ::  a -> MarkedList a b -> MarkedList a c

safeHead                    ::  MarkedList a Safe -> a
safeHead (Cons x _)          =  x


silly 0                      =  Nil
silly 1                      =  Cons () Nil
silly n                      =  Cons () $ silly (n-1)
Run Code Online (Sandbox Code Playgroud)

使用Kind Signature,我可以使用Cons构造函数来构造和模式匹配安全和不安全的MarkedLists.虽然我明白发生了什么,但遗憾的是我难以建立任何关于Kind Signature如何允许这种情况的直觉.为什么我需要种类签名?Kind Signature做什么?

Die*_*Epp 15

类型签名与值相同的方式,类型签名适用于类型.

f :: Int -> Int -> Bool
f x y = x < y
Run Code Online (Sandbox Code Playgroud)

这里,f获取两个参数值并生成结果值.类型的等价物可以是:

data D a b = D a b
Run Code Online (Sandbox Code Playgroud)

该类型D采用两种参数类型并生成结果类型(它是* -> * -> *).例如,D Int String是一种类型(有种类*).部分应用程序D Int具有类型* -> *,与部分应用程序的f 15类型相同Int -> Bool.

所以我们可以将上面的内容重写为:

data D :: * -> * -> * where
  D :: a -> b -> D a b
Run Code Online (Sandbox Code Playgroud)

在GHCi中,您可以查询类型和种类:

> :type f
f :: Int -> Int -> Bool
> :kind D
D :: * -> * -> *
Run Code Online (Sandbox Code Playgroud)

  • 在其他情况下,您可能希望指定其他类型.例如,`data X a = X`.这里,`X`有种类`* - >*`,其参数必须是无效的.您可以使用`data X(a ::* - >*)= X`为其参数指定一元类型,因此`X`将具有类型`(* - >*) - >*`,因此您可以进行参数化`X`在仿函数或monad或者不是nullary的东西.我认为在你说的例子中没有必要. (5认同)
  • @ExternalReality :( re:"Kind Signature提供了多少额外的东西?",除了Dietrich Epp所说的)人们可以认为`MarkedList ab where where ...`语法有点误导,因为它看起来像名字`a`和`b`绑定在主体中使用(在`where`之后),而实际上,它们根本没有效果(每个构造函数绑定它自己的名字).编写`MarkedList ::* - >* - >*`避免这种情况.但这只是一种品味问题. (3认同)