首页 > 解决方案 > 如何接收从函子构建的类型作为 OCaml 中函数的参数?

问题描述

我正在研究仿函数,我试图接收一个Module.tas 参数,其中Module是仿函数调用的结果,SomeFunctor(sig type t = int end)但我收到Unbound type constructor FooInt.t

这是代码

module type Foo_S = sig
  type t
end

module type Foo = sig
  type t
  val id : t -> t
end

module FooExtend(Arg : Foo_S) : (Foo with type t := Arg.t) = struct
  let id a = a
end

module FooInt = FooExtend(Int)
module FooString = FooExtend(String)

let () =
  assert (FooInt.id 1 = 1);
  assert (FooString.id "x" = "x")

module FooSimple = struct type t = int end

let foo (x : FooInt.t) = (* This doens't compile: Unbound type constructor FooInt.t *)
  FooInt.id x

let foo' (x : FooSimple.t) = (* This works fine *)
  FooInt.id x

标签: ocamlfunctor

解决方案


需要进行两处更改,1)type t需要在模块中定义,2)不要使用破坏性替换:

module FooExtend(Arg : Foo_S) : (Foo with type t = Arg.t) = struct
  type t = Arg.t
  let id a = a
end

问题是破坏性替换 ( type t := Arg.t) 替换了每次出现的twith Arg.t。相反,您希望使用“共享约束”( type t = Arg.t) 来指定类型相等性。

请注意两者之间生成的模块签名的差异:

module FooExtend(Arg : Foo_S) : (Foo with type t := Arg.t) = struct
  type t = Arg.t
  let id a = a
end

module FooExtend : functor (Arg : Foo_S) -> sig 
  val id : Arg.t -> Arg.t
end
module FooExtend(Arg : Foo_S) : (Foo with type t = Arg.t) = struct
  type t = Arg.t
  let id a = a
end

module FooExtend : functor (Arg : Foo_S) -> sig
    type t = Arg.t
    val id : t -> t
end

推荐阅读