请考虑以下数据类型:
data Get (statusCode :: Nat)
Run Code Online (Sandbox Code Playgroud)
实际上,它是来自servant的简化类型构造函数,然后在类型级API中使用,如下所示:
type API = "users" :> Verb 'GET 200 '[JSON] [User]
Run Code Online (Sandbox Code Playgroud)
出于我们的目的,我们可以将API减少到
type API = Get 200
Run Code Online (Sandbox Code Playgroud)
现在,限制状态代码Nat
是太松散了,允许定义不存在的HTTP状态代码:
type API = Get 999
Run Code Online (Sandbox Code Playgroud)
因此,问题是:有没有办法限制可以应用于Get
类型构造函数的自然集?
为清楚起见,我将省略代码示例中的所有编译指示和导入.
statusCode
解决这个问题的一个明显方法是为状态代码定义一个单独的ADT,并使用它代替Nat
利用数据类型提升.
data StatusCode = HTTP200 | HTTP201 | HTTP202
data Get (statusCode :: StatusCode)
Run Code Online (Sandbox Code Playgroud)
但是,这是一个重大变化,需要修改主要版本并重写所有用户的定义.我怀疑限制代码的好处是值得的.
此扩展允许对我们的类型变量进行直接约束
data IsStatusCode statusCode => Get (statusCode :: Nat)
Run Code Online (Sandbox Code Playgroud)
但它要求用户将约束添加到他们的所有声明中.再次,一个突破性的变化.此外,DatatypeContexts
已被弃用.
我们可以Get'
使用类型族从下面的示例中有条件地创建,但由于某种原因,声明类型别名可以快速编译.为了得到一个错误,我们需要构造一个这种类型的值,这也是一个突破性的变化.
data …
Run Code Online (Sandbox Code Playgroud) 想象一种语言,它不允许数据类型的多个值构造函数.而不是写作
data Color = White | Black | Blue
Run Code Online (Sandbox Code Playgroud)
我们会有
data White = White
data Black = Black
data Blue = Black
type Color = White :|: Black :|: Blue
Run Code Online (Sandbox Code Playgroud)
where :|:
(这里不是|
为了避免与sum类型混淆)是一个内置的类型union运算符.模式匹配可以以相同的方式工作
show :: Color -> String
show White = "white"
show Black = "black"
show Blue = "blue"
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,与副产品相比,它会产生扁平结构,因此您无需处理注射.而且,与sum类型不同,它允许随机组合类型,从而产生更大的灵活性和粒度:
type ColorsStartingWithB = Black :|: Blue
Run Code Online (Sandbox Code Playgroud)
我相信构造递归数据类型也不是问题
data Nil = Nil
data Cons a = Cons a (List a)
type List a = Cons a :|: Nil …
Run Code Online (Sandbox Code Playgroud) 根据规范,这个运算符被称为bit clear:
&^ bit clear (AND NOT) integers
Run Code Online (Sandbox Code Playgroud)
我以前从未听说过这样的操作员,我想知道它为什么有用.
它似乎采用左操作数并禁用右操作数中打开的所有位.是否有关于运营商的正式描述?我注意到的另一件事是它不是可交换的.Pococode与comarison ^
:
11110 &^ 100 //11010
11110 ^ 100 //11010
11110 &^ 0 //11110
11110 ^ 0 //11110
11110 &^ 11110 //0
11110 ^ 11110 //0
11110 &^ 111 //11000
11110 ^ 111 //11001
111 &^ 11110 //1
111 ^ 11110 //11001
Run Code Online (Sandbox Code Playgroud)