首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >GADT模式匹配

GADT模式匹配
EN

Stack Overflow用户
提问于 2020-06-29 11:43:51
回答 1查看 114关注 0票数 1

我最近一直在使用GADT,我想知道是否有人可以为我指出正确的方向,学习如何键入它,以便它可以编译,如果它可能的话,或者如果我过于复杂的事情。

我在这里看到了一些关于GADT模式匹配的其他答案,但这似乎有点不同。

我见过这样的事情来表示一个没有可能的值的类型:

代码语言:javascript
复制
module Nothing = {
  type t =
    | Nothing(t);
};

所以我想用它来锁定这个Exit.t类型,这样我就可以有一个Exit.t('a,Nothing.t)类型来表示成功案例,捕捉到没有可恢复的失败值这一事实。

代码语言:javascript
复制
module Exit = {
  type t('a, 'e) =
    | Success('a): t('a, Nothing.t)
    | Failure('e): t(Nothing.t, 'e);

这看起来还不错,直到我尝试为它编写一个flatMap函数。

代码语言:javascript
复制
  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 etype a e离开'a1,但我似乎就是不能理解。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-06-29 17:27:52

(我使用下面的OCaml语法,因为这个问题也被标记为"ocaml",但同样的语法应该是合理的。)

首先,您的类型Nothing.t不是空的。循环值Nothing (Nothing (Nothing (...)))是一个有效的居民。如果您确实希望类型为空,请不要放置任何构造函数。

其次,正如您所猜到的,在flat_map中,Failure分支强制使用Nothing.t实例化'a1。这是没有办法的;这不是编译器的缺点,只是解释这段代码的唯一方法。

第三,你把事情搞得有点太复杂了,因为为了实现你的目标,Exit.t根本不需要是一个GADT。

下面是一个更简单的例子,它表明,如果Nothing.t实际上是空的,那么编译器正确地允许不相关的分支。

代码语言:javascript
复制
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 *)
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62630864

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档