仿函数 - 导入类型
Functors - Import type
我是 OCaml 的新手,正在尝试学习函子。到目前为止,我有以下内容:
utop # module type Foo = sig
type t = {
foo : int;
bar : int;
}
val create : int -> int -> t
val get : t -> int
end;;
utop # module FooImpl = struct
type t = {
foo : int;
bar : int;
}
let create x y = {
foo = x;
bar = y;
}
let get w = w.foo
end;;
现在我将尝试定义我的仿函数,它将对 Foo 类型的模块进行操作并替换 get
函数。
utop # module Functor (F : Foo) : Foo with type t := F.t = struct
let create = F.create
let get w = w.bar
end;;
Error: Unbound record field bar
它不知道记录的类型。我会尝试定义它:
utop # module Functor (F : Foo) : Foo with type t := F.t = struct
type t = {
foo : int;
bar : int;
}
let create = F.create
let get w = w.bar
end;;
Error: Signature mismatch: ... Values do not match:
val get : t -> int
is not included in
val get : F.t -> int
所以OCaml不知道t
和F.t
实际上是同一个类型。所以我会试着说:
utop # module Functor (F : Foo) : Foo with type t := F.t = struct
type t = F.t
let create = F.create
let get w = w.bar
end;;
Error: Unbound record field bar
我做错了什么?
如果我这样定义 get
,你第一次尝试定义 Functor 对我有用:
let get w = w.F.bar
这是我的完整会话:
# module type Foo = sig (... ELIDED...) end;;
module type Foo =
sig
type t = { foo : int; bar : int; }
val create : int -> int -> t
val get : t -> int
end
# module FooImpl = struct (...ELIDED...) end;;
module FooImpl :
sig
type t = { foo : int; bar : int; }
val create : int -> int -> t
val get : t -> int
end
# module Functor (F: Foo) : Foo with type t := F.t = struct
let create = F.create
let get w = w.F.bar
end;;
module Functor :
functor (F : Foo) ->
sig val create : int -> int -> F.t val get : F.t -> int end
# module F2 = Functor(FooImpl);;
module F2 :
sig val create : int -> int -> FooImpl.t val get : FooImpl.t -> int end
# let c1 = FooImpl.create 8 9;;
val c1 : FooImpl.t = {FooImpl.foo = 8; bar = 9}
# FooImpl.get c1;;
- : int = 8
# let c2 = F2.create 8 9;;
val c2 : FooImpl.t = {FooImpl.foo = 8; bar = 9}
# F2.get c2;;
- : int = 9
字段名称属于定义它们的模块范围。例如,如果您在模块 Foo
中定义记录
module Foo = struct
type t = { bar : int; baz : int; quz : int }
end
然后为了访问模块外的这个字段 Foo
你需要使用完全限定的名称,例如
let bar_of_foo x = x.Foo.bar
在模式匹配中字段名也可以被限定,这样就可以编写上面的函数如下:
let bar_of_foo {Foo.bar} = bar
您只需限定一个名称,因此当您需要一次访问多个字段时,此语法很有用:
let sum_of_foo {Foo.bar; baz; quz} = bar + baz + quz
最后,您可以 open
模块将记录名称引入当前范围。您可以使用本地打开语法 Foo.(expr)
来本地化打开的影响:
let bar_of_foo x = Foo.(x.bar)
在您的示例中,字段在模块 F
中定义,它是仿函数 Functor
的参数。因此,您需要使用上述方法之一来访问它的字段,例如,
module Functor (F : Foo) : Foo with type t := F.t = struct
open F
let create = F.create
let get w = w.bar
end
我是 OCaml 的新手,正在尝试学习函子。到目前为止,我有以下内容:
utop # module type Foo = sig
type t = {
foo : int;
bar : int;
}
val create : int -> int -> t
val get : t -> int
end;;
utop # module FooImpl = struct
type t = {
foo : int;
bar : int;
}
let create x y = {
foo = x;
bar = y;
}
let get w = w.foo
end;;
现在我将尝试定义我的仿函数,它将对 Foo 类型的模块进行操作并替换 get
函数。
utop # module Functor (F : Foo) : Foo with type t := F.t = struct
let create = F.create
let get w = w.bar
end;;
Error: Unbound record field bar
它不知道记录的类型。我会尝试定义它:
utop # module Functor (F : Foo) : Foo with type t := F.t = struct
type t = {
foo : int;
bar : int;
}
let create = F.create
let get w = w.bar
end;;
Error: Signature mismatch: ... Values do not match:
val get : t -> int
is not included in
val get : F.t -> int
所以OCaml不知道t
和F.t
实际上是同一个类型。所以我会试着说:
utop # module Functor (F : Foo) : Foo with type t := F.t = struct
type t = F.t
let create = F.create
let get w = w.bar
end;;
Error: Unbound record field bar
我做错了什么?
如果我这样定义 get
,你第一次尝试定义 Functor 对我有用:
let get w = w.F.bar
这是我的完整会话:
# module type Foo = sig (... ELIDED...) end;;
module type Foo =
sig
type t = { foo : int; bar : int; }
val create : int -> int -> t
val get : t -> int
end
# module FooImpl = struct (...ELIDED...) end;;
module FooImpl :
sig
type t = { foo : int; bar : int; }
val create : int -> int -> t
val get : t -> int
end
# module Functor (F: Foo) : Foo with type t := F.t = struct
let create = F.create
let get w = w.F.bar
end;;
module Functor :
functor (F : Foo) ->
sig val create : int -> int -> F.t val get : F.t -> int end
# module F2 = Functor(FooImpl);;
module F2 :
sig val create : int -> int -> FooImpl.t val get : FooImpl.t -> int end
# let c1 = FooImpl.create 8 9;;
val c1 : FooImpl.t = {FooImpl.foo = 8; bar = 9}
# FooImpl.get c1;;
- : int = 8
# let c2 = F2.create 8 9;;
val c2 : FooImpl.t = {FooImpl.foo = 8; bar = 9}
# F2.get c2;;
- : int = 9
字段名称属于定义它们的模块范围。例如,如果您在模块 Foo
module Foo = struct
type t = { bar : int; baz : int; quz : int }
end
然后为了访问模块外的这个字段 Foo
你需要使用完全限定的名称,例如
let bar_of_foo x = x.Foo.bar
在模式匹配中字段名也可以被限定,这样就可以编写上面的函数如下:
let bar_of_foo {Foo.bar} = bar
您只需限定一个名称,因此当您需要一次访问多个字段时,此语法很有用:
let sum_of_foo {Foo.bar; baz; quz} = bar + baz + quz
最后,您可以 open
模块将记录名称引入当前范围。您可以使用本地打开语法 Foo.(expr)
来本地化打开的影响:
let bar_of_foo x = Foo.(x.bar)
在您的示例中,字段在模块 F
中定义,它是仿函数 Functor
的参数。因此,您需要使用上述方法之一来访问它的字段,例如,
module Functor (F : Foo) : Foo with type t := F.t = struct
open F
let create = F.create
let get w = w.bar
end