servant paper的介绍包含以下示例API类型:
type Echo = "echo"
:> ReqBody ’[PlainText] String
:> Get ’[PlainText] String
我试图理解这个例子。它似乎是定义一个类型的同义词,但似乎涉及一些我以前从未见过的事情。
以下是我提出的三个问题:
"echo"
是一个字符串文字。我认为这些仅用于定义特定字符串,并且在类型声明中使用时不知道这意味着什么。
:>
? “servant”包中此符号的定义似乎是defined here,如下所示:
data (path :: k) :> a
deriving (Typeable)
infixr 9 :>
我猜想:>
对应于api字符串中的/
,但是看不出这个定义会如何实现。
这是我第一次看到除函数类型->
以外的非字母数字类型。
[PlainText]
我理解只是代表一个PlainText元素列表,但相反我不明白’[PlainText]
的含义。
答案 0 :(得分:1)
类型定义中有一个字符串文字吗?
DataKinds
扩展名允许您在类型签名中使用这些字符串文字。它们中的每一个代表不同的类型。他们都属于那种Symbol
;我们可以使用ghci中的:kind
命令来测试它:
Prelude> :set -XDataKinds
Prelude> :kind "foo"
"foo" :: GHC.Types.Symbol
因为在Haskell中只有类型*
具有值,所以这些类型级别的字符串不是有人值守的。但是functions可以让你获得相应的术语级别字符串。
符号是什么:>?
TypeOperators
扩展名允许您使用运算符名称定义类型。这对于主要用于组合其他类型的参数化类型很有用。请注意,:>
有两个类型参数但没有值级构造函数:它仅在类型级别使用。
列表类型之前的撇号是什么意思?
DataKinds
不只是启用符号。它允许您将值构造函数用作 types ,并且这些构造函数的类型依次变为 types 。例如:
Prelude> :set -XDataKinds
Prelude> :kind True
True :: Bool
这些推广的构造函数不会被任何术语居住(因为它们具有*
以外的种类。)
特别是,我们可以将列表提升为类型级别。但这会产生一些含糊之处。签名中的[Int]
是什么?它是Int
的列表类型(具有种类*
)还是具有一个元素的类型级列表,类型Int
?撇号表明我们正在讨论类型级列表。
Prelude> :set -XDataKinds
Prelude> :kind [Int]
[Int] :: *
Prelude> :kind '[Int]
'[Int] :: [*]
Prelude> :kind '[True]
'[True] :: [Bool]
多个元素的类型级列表不需要撇号,因为没有歧义:
Prelude> :kind [Int,Int]
[Int,Int] :: [*]