ocaml - GADT 模式匹配
问题描述
我最近一直在玩 GADT,想知道是否有人可以为我指出正确的方向来学习如何键入它以便编译,如果可能的话,或者我是否过于复杂。
我在这里看到了 GADT 模式匹配的其他一些答案,但这似乎有点不同。
我见过这种类型的事情来表示没有可能值的类型:
module Nothing = {
type t =
| Nothing(t);
};
所以我想用它来锁定这个 Exit.t 类型,这样我就可以有一个 Exit.t('a, Nothing.t) 类型来表示 Success 情况,捕捉到没有可恢复的 Failure 值的事实。
module Exit = {
type t('a, 'e) =
| Success('a): t('a, Nothing.t)
| Failure('e): t(Nothing.t, 'e);
这似乎没问题,直到我尝试为它编写一个 flatMap 函数。
let flatMap: ('a => t('a1, 'e), t('a, 'e)) => t('a1, 'e) = (f, exit) =>
switch (exit) {
| Success(a) => f(a)
| Failure(_) as e => e
};
};
实际上,它推断类型 Exit.t 始终是 Exit.t(Nothing.t, Nothing.t) ,我有点理解,因为失败案例中的类型会将第一个类型设置为 Nothing,而成功案例会将第二种类型设置为 Nothing。
我已经尝试了我知道的一件事,使用type a
. 我试过离开type a a1 e
,但我似乎无法捕捉到这个想法。type a e
'a1
解决方案
(我正在使用下面的 OCaml 语法,因为该问题也被标记为“ocaml”,但同样适用于 Reason。)
首先,您的类型Nothing.t
不为空。循环值Nothing (Nothing (Nothing (...)))
是有效的居民。如果您真的希望类型为空,请不要放置任何构造函数。
其次,正如您所猜测的,在 中flat_map
,您的Failure
分支强制'a1
使用 实例化Nothing.t
。没有办法解决这个问题。这不是编译器的缺陷,只是解释这段代码的唯一方法。
第三,你让事情变得有点太复杂了,因为Exit.t
不必首先成为 GADT 来实现你的目标。
下面是一个更简单的示例,表明如果Nothing.t
实际上是空的,则编译器正确地允许不相关的分支。
type nothing = |
type ('a, 'b) result =
| Success of 'a
| Failure of 'b
let only_success (x : ('a, nothing) result) : 'a =
match x with
| Success v -> v
| Failure _ -> . (* this branch can be removed, as it is correctly inferred *)
推荐阅读
- jenkins - Jenkins pipeline to SSH into an instance and call a function
- mysql - 这个 mySQL 查询有什么问题?(连接和转换)
- r - How to obtain unique set of rows in nested data frame?
- python - Tensorflow object detection - own classes inference graph train/export error (tensor shape)
- git - How could I backup/version control my file (having IDE settings) at some other path in git?
- wagtail - 让鹡鸰对文档使用正确的 mime 类型
- android - 将选项卡添加到操作栏时,对象引用未设置为对象的实例
- asp.net - 当我尝试更改某些内容时,Asp.net 核心没有更新
- jquery - 为什么我不能限制选中复选框的数量?
- html - 显示:弹性和无响应的照片 HTML + CSS