我经常听说F#缺乏对OCaml行类型的支持,这使得语言比F#更强大。
他们是什么?它们是代数数据类型,例如总和类型(有区别的联合)还是产品类型(元组,记录)?是否可以在其他方言中写行类型,例如F#?
答案 0 :(得分:10)
行类型很奇怪。非常强大。
行类型用于在OCaml中实现对象和多态变体。
但首先,如果没有行类型,我们不能:
type t1 = { a : int; b : string; }
type t2 = { a : int; c : bool; }
let print_a x = print_int x.a
let ab = { a = 42; b = "foo"; }
let ac = { a = 123; c = false; }
let () =
print_a ab;
print_a ac
此代码当然会拒绝编译,因为print_a
必须具有唯一类型:t1
或t2
,但不能同时使用两者。但是,在某些情况下,我们可能需要这种确切的行为。这就是行类型的用途。这就是他们所做的:一种更“灵活”的类型。
在OCaml中,行类型主要有两种用途:objects和polymorphic variants。在代数方面,对象为您提供“行产品”和多态变体“行和”。
关于行类型的注意事项是,你最终可以使用一些子类型进行声明,并且非常直观的类型和语义(特别是在案例类中)。
您可以查看this paper了解详情。
答案 1 :(得分:7)
我用他的例子完成PatJ's excellent answer,用类写。
鉴于以下课程:
class t1 = object
method a = 42
method b = "Hello world"
end
class t2 = object
method a = 1337
method b = false
end
以下对象:
let o1 = new t1
let o2 = new t2
您可以写下以下内容:
let print_a t = print_int t#a;;
val print_a : < a : int; .. > -> unit = <fun>
print_a o1;;
42
- : unit = ()
print_a o2;;
1337
- : unit = ()
您可以在print_a
签名中看到行类型。 < a : int; .. >
字面意思是&#34;任何至少包含带有签名a
&#34; 的方法int
的对象。