3

仆人论文的介绍包含以下示例 API 类型:

type Echo = "echo"
          :> ReqBody ’[PlainText] String
          :> Get ’[PlainText] String

我试图理解这个例子。它似乎在定义一个类型同义词,但似乎涉及到一些我以前没有见过的东西。

以下是我对此的三个问题:

  1. 类型定义中如何存在字符串文字?

"echo"是一个字符串文字。我认为这些仅用于定义特定的字符串,并且不知道在类型声明中使用时这意味着什么。

  1. 符号是什么:>

'servant' 包中这个符号的定义似乎是在这里定义的,看起来像这样:

data (path :: k) :> a
    deriving (Typeable)
infixr 9 :>

我猜这:>对应/于 api 字符串中的 a,但看不到这个定义是如何实现的。

这是我第一次看到函数类型以外的非字母数字类型->

  1. 列表类型前的撇号是什么意思?

[PlainText]我会理解简单地表示一个 PlainText 元素的列表,但相比之下我不明白是什么’[PlainText]意思。

4

1 回答 1

1

类型定义中如何存在字符串文字?

DataKinds扩展允许您在类型签名中使用这些字符串文字。它们中的每一个都代表不同的类型。他们都属于那种Symbol;我们可以使用:kindghci 中的命令进行测试:

Prelude> :set -XDataKinds
Prelude> :kind "foo"
"foo" :: GHC.Types.Symbol

因为在 Haskell 中只有种类的类型*有值,所以这些类型级别的字符串是不存在的。但是有一些函数可以让您获得相应的术语级字符串。

符号是什么:>?

TypeOperators扩展允许您使用运算符名称定义类型。这对于主要用于组合其他类型的参数化类型很有用。请注意,它:>有两个类型参数,但没有值级别的构造函数:它仅用于类型级别。

列表类型前的撇号是什么意思?

DataKinds不仅仅是启用符号。它允许您将值构造函数用作类型,并且这些构造函数的类型依次变为种类。例如:

Prelude> :set -XDataKinds
Prelude> :kind True
True :: Bool

这些提升的构造函数不包含任何术语(因为它们具有除 之外的种类*)。

特别是,我们可以将列表提升到类型级别。但这会产生一些歧义。[Int]签名中有什么?它是 s 的列表类型Int(具有 kind *)还是具有一个元素的类型级列表 type Int?撇号清楚地表明我们正在谈论类型级别的列表。

Prelude> :set -XDataKinds
Prelude> :kind [Int]
[Int] :: *
Prelude> :kind '[Int]
'[Int] :: [*]
Prelude> :kind '[True]
'[True] :: [Bool]

多个元素的类型级列表不需要撇号,因为没有歧义:

Prelude> :kind [Int,Int]
[Int,Int] :: [*]
于 2017-06-08T21:21:13.400 回答