我是 F# 新手,所以如果这是一个愚蠢的问题或者语法可能有点不对,请提前原谅我。希望无论如何都可以理解问题的要点。
我想要实现的是组合 eg Result's (或 anEither或类似的东西)具有不同错误类型(受歧视联合)的可能性,而无需创建包括其他两个受歧视联合的并在内的明确受歧视联合。
让我举一个例子。
假设我有一个这样Person定义的类型:
type Person =
{ Name: string
Email: string }
Run Code Online (Sandbox Code Playgroud)
假设您有一个验证名称的函数:
type NameValidationError =
| NameTooLong
| NameTooShort
let validateName person : Result<Person, NameValidationError>
Run Code Online (Sandbox Code Playgroud)
另一个验证电子邮件地址:
type EmailValidationError =
| EmailTooLong
| EmailTooShort
let validateEmail person : Result<Person, EmailValidationError>
Run Code Online (Sandbox Code Playgroud)
现在我想编写validateNameand validateEmail,但问题是 中的错误类型Result有不同的类型。我想要实现的是一个函数(或运算符),它允许我做这样的事情:
let validatedPerson = person |> validateName |>>> validateEmail
Run Code Online (Sandbox Code Playgroud)
(|>>>是“魔术运算符”)
通过使用|>>>错误类型validatedPerson将是 …
鉴于这些类型
type a = [ `A ]
type b = [ a | `B | `C ]
Run Code Online (Sandbox Code Playgroud)
和这个功能
let pp: [< b] -> string =
function | `A -> "A"
| `B -> "B"
| `C -> "C"
Run Code Online (Sandbox Code Playgroud)
a正如预期的那样,应用类型值的作品没有问题:
let a: a = `A
let _ = pp a
Run Code Online (Sandbox Code Playgroud)
但是,如果修改该函数以包含通配符模式
let pp: [< b] -> string =
function | `A -> "A"
| `B -> "B"
| _ -> "?"
Run Code Online (Sandbox Code Playgroud)
即使其他一切都保持不变,它现在会产生以下错误(打开let _ = pp a):
此表达式具有类型b - …
我有以下代码:
module Test : sig
type +'a t
val make : int -> [< `a | `b] t
end = struct
type 'a t = Foo of int | Bar of string
let make = function
| 0 -> (Foo 0 : [`a] t)
| _ -> (Bar "hi" : [`a] t)
end
Run Code Online (Sandbox Code Playgroud)
您可能会注意到,抽象类型'a t在其类型参数中被声明为协变'a,并且make构造函数被声明为返回多态变体case 或的子类型.ab
在我的实现中make,返回子类型[a] t仍应遵循协方差规则,因为子类型在返回类型位置.
但是,我收到以下错误:
Error: Signature mismatch:
...
Values do not …Run Code Online (Sandbox Code Playgroud) 假设我有一个由多个多态变体(协变)组成的类型,如下所示:
[> `Ok of int | `Error of string]
Run Code Online (Sandbox Code Playgroud)
让我们进一步假设我想将此定义分解为某种类型构造函数和一个具体类型int。我的第一次尝试如下:
type 'a error = [> `Ok of 'a | `Error of string]
Run Code Online (Sandbox Code Playgroud)
然而,使用这样的定义会产生一个非常奇怪的类型错误,提到一个'b没有出现在定义中任何地方的类型变量。
$ ocaml
OCaml version 4.07.0
# type 'a error = [> `Ok of 'a | `Error of string ];;
Error: A type variable is unbound in this type declaration.
In type [> `Error of string | `Ok of 'a ] as 'b the variable 'b is unbound
Run Code Online (Sandbox Code Playgroud)
这'b是一个自动生成的名称,添加一个显式'b将变量转换为'c …
ocaml parametric-polymorphism polymorphic-variants row-polymorphism
我正在编写一个 Prolog 系统,并且使用多态变体来表示 Prolog 术语。
特别是,我使用多态变体(而不是常规变体),因此我可以进行子类型化,同时确保 OCaml 对子类型的匹配进行出色的详尽检查。
到目前为止,一切都很好!
我曾多次阅读过有关 GADT 的内容(在 Discuss.ocaml.org 和 realworldocaml.org 上)。对我来说,GADT 似乎提供了类似的功能,但内存占用更小:具有多个参数的情况的多态变体需要一个额外的指针,而常规变体不需要。
到目前为止,我还没有能够成功使用 GADT,所以这是我的问题:
是否有一种简单、直接的方法将使用多态变体的代码转换为 GADT?在一般情况下这甚至可能吗?
先感谢您!