Interface 具有不同特异性水平的OCaml类型
我试图在OCaml中模拟一个接口,并使用“类型”构造。我有两种类型:Interface 具有不同特异性水平的OCaml类型,interface,ocaml,Interface,Ocaml,我试图在OCaml中模拟一个接口,并使用“类型”构造。我有两种类型: type fooSansBar = {a: string; b: int};; type fooConBar = {a:string; b:int; bar:char};; type fooBar = { a: string; b: int; bar: char option } …并希望定义一个特定的fooSansBar: let fsb = {a="a"; b=3};; …但我被告知条形字段未定义。由此看来,与我在匹
type fooSansBar = {a: string; b: int};;
type fooConBar = {a:string; b:int; bar:char};;
type fooBar = { a: string; b: int; bar: char option }
…并希望定义一个特定的fooSansBar:
let fsb = {a="a"; b=3};;
…但我被告知条形字段未定义。由此看来,与我在匹配fooSansBar签名时传递的值相反,系统认为我正在尝试创建一个fooConBar。如果存在上面定义的两种类型,是否可以创建fooSansBar
另外(因为我是OCaml新手),有没有更好的方法来模拟接口?第二种类型重新定义了a和b,有效地隐藏了第一种类型,这就是为什么不能再构造它的原因。您可以在不同的模块中定义这些类型,但这与为a和b使用不同的名称相同 只有当您不尝试从另一个接口“派生”而只是实现它时,才能使用这些构造
如果希望在Ocaml中使用这些面向对象的概念,可以查看对象系统,或者根据您的问题,查看模块系统。或者,您可以尝试以功能性的方式解决您的问题。您试图解决什么问题?在OCaml中,记录类型中的字段名必须是唯一的,因此您定义的两种类型不能同时共存。Caml是我所知道的唯一一种具有此属性的语言 因为第二个定义隐藏了第一个定义,所以当编译器看到a和b字段时,它希望它们属于
fooConBar
类型,因此抱怨缺少bar字段
如果您试图模拟一个接口,在Caml中正确的功能方法是定义一个模块类型
module type FOO_CON_BAR = sig
val a : string
val b : int
val bar : char
end
还有一个例子:
module Example = struct
let a = "hello"
let b = 99
let c = '\n'
end
使用模块和模块类型,您还可以获得子类型;没有必要求助于物体
另外,我的凸轮生锈了;语法可能已关闭。OCaml中有几种可能的解决方案,具体取决于您如何使用提供的代码。最简单的方法是将两种类型结合起来:
type fooSansBar = {a: string; b: int};;
type fooConBar = {a:string; b:int; bar:char};;
type fooBar = { a: string; b: int; bar: char option }
另一种解决方案是用对象替换记录,因为对象支持子类型(并且可以推断其类型,因此无需声明类型!):
#让fsb=object
方法a=“a”
方法b=3
完;;;
val fsb:=
#金融稳定委员会a,金融稳定委员会b;;
-:string*int=(“a”,3)
在OCaml中,不可能在同一范围内存在两种具有相交字段集的记录类型
如果确实需要将记录类型与相交字段集一起使用,则可以通过将这些类型包含在它们自己的专用模块中来绕过此限制:
module FooSansBar = struct type t = {a:string; b:int} end
module FooConBar = struct type t = {a:string; b:int; bar:char} end
然后可以像这样构造这些类型的实例:
let fsb = {FooSansBar.a="a"; b=3}
let fcb = {FooConBar.a="a"; b=4; bar='c'}
这些实例具有以下类型:
fsb : FooSansBar.t
fcb : FooConBar.t
OCaml提供了两种实现接口的方法。如前所述,其中之一是模块类型 另一个是类类型。您可以编写类类型(接口)
fooSansBar
:
class type fooSansBar = object
method a: string
method b: int
end
和类类型fooConBar:
class type fooConBar = object
inherit fooSansBar
method bar: char
end
这将允许您在需要foosanBar
的任何位置使用foosanBar
。现在可以使用类型推断创建fooSansBar
:
let fsb = object
method a = "a"
method b = 3
end
现在,fsb
的类型恰好是Jon指出的
,但由于OCaml的结构子类型,它完全可以用作fooSansBar