我一直在使用多态变体对结果类型进行错误处理(取自http://keleshev.com/composable-error-handling-in-ocaml),对于穷举检查非常有用。我最近遇到了需要在函子中注释结果类型的需求,但不确定是否可行。这是一个片段,其中包含对我要完成的操作的一些评论:
open Belt;
/* A quick example of what's working for us right now. This is fine and
the result error type is [> `Error1 | `Error2 ] */
let res = Result.flatMap(Result.Error(`Error1), _ => Result.Error(`Error2));
/* A really generic version of what what we're trying to do */
module type General = {
type t;
type error;
let res: Result.t(t, error);
};
module Make = (M: General) => {
let res = M.res;
};
module Specific1 =
Make({
type t = string;
type error = [ | `Specific1Error];
let res = Result.Error(`Specific1Error);
});
module Specific2 =
Make({
type t = int;
type error = [ | `Specific2Error];
let res = Result.Error(`Specific2Error);
});
/* This definitely doesn't compile because the two error types
aren't the same but wondering if anything above can be changed so it
understands the error type is [> `Specific1Error | `Specific2Error] */
let res = Result.flatMap(Specific1.res, _ => Specific2.res);
答案 0 :(得分:2)
这不是一个完整的答案,但是它提供了更多信息以及一种可能的解决方案或解决方法。
可以通过向特定的组合类型添加显式强制来获得最后一行的编译:
let res =
Result.flatMap(
Specific1.res :> Result.t(string, [`Specific1Error | `Specific2Error]),
_ => (Specific2.res :> Result.t(int, [`Specific1Error | `Specific2Error])));
在这里,它们都被强制为同一类型,所以我们都很好。至于为什么需要明确的原因,我的理解是,这是为了防止错误地构造函数引起意外错误。在this answer中查看更多信息。
如果type error
指定了下限,则不必显式,如下所示:
let error1 : Result.t(int, [> `Error1]) = Result.Error(`Error1);
let error2 : Result.t(int, [> `Error2]) = Result.Error(`Error2);
let res = Result.flatMap(error1, _ => error2);
但是由于上限和下限多态变体具有隐式类型变量,因此我们至少必须将type error
更改为type error('a)
。不幸的是,即使那样,我仍然不确定如何使模块签名与实现保持一致,例如:
type error('a) = [> | `Specific1Error] as 'a;
失败
Signature mismatch:
...
Type declarations do not match:
type 'a error = 'a constraint 'a = [> `Specific1Error ]
is not included in
type 'a error
Their constraints differ.
也不可能强制转换为下限多态变体类型,但我不确定为什么是这样:
let res =
Result.flatMap(
Specific1.res :> Result.t(string, [> `Specific1Error]),
_ => (Specific2.res :> Result.t(int, [> `Specific2Error])));
失败
This has type:
(int, [ `Specific2Error ]) Result.t
But somewhere wanted:
(int, [ `Specific1Error ]) Result.t
These two variant types have no intersection
表示将忽略边界。
我在几个方面都达到了我的知识极限,但是我向您的问题添加了ocaml,因为它有几个具有丰富知识的追随者,希望可以将最后的内容整合在一起。
答案 1 :(得分:0)
您是否有必要在return str.split(/\s+|_|(?=[A-Z])/).toLowerCase().join('-')
模块签名中密封error
类型的原因?既然您似乎需要知道所有这些错误变量的总和才能注释最终的General
值,那么您可以执行以下操作吗? (请原谅为标准OCaml语法和习语的翻译。)
res