我想定义一个依赖于其他模块的模块类型。我以为可以用函子来做,但是我相信函子只是从模块到模块的映射,不可能使用它们来定义从模块到模块类型的映射。
这是我想做的事的一个例子:
module type Field =
sig
type t
val add : t -> t -> t
val mul : t -> t -> t
end
module type Func (F1 : Field) (F2 : Field) =
sig
val eval : F1.t -> F2.t
end
module FuncField (F1 : Field) (F2 : Field) (F : Func F1 F2) =
struct
let eval a = F.eval a
let add a b = F2.add (F.eval a) (F.eval b)
let mul a b = F2.mul (F.eval a) (F.eval b)
end
我有一个Field
模块类型,例如实数和有理数,我想从一个字段到另一个字段定义函数Func
的类型,即F1.t -> F2.t
对于任何两个给定的模块F1
,F2
。有了这些模块类型之后,我可以定义FuncField
,它使用F1
,F2
,F
并基本上用F.eval
来扩充add
和mul
。
运行代码时,在定义Error: Syntax error
的行中得到通用的Func
。有没有办法在OCaml中定义类似的东西?
我不确定这是否需要依赖类型,但是我对Coq有点依赖,因为Coq具有依赖类型,并且在定义等效构造时也不会抱怨:
Module Type Field.
Parameter T : Type.
Parameter add : T -> T -> T.
Parameter mul : T -> T -> T.
End Field.
Module Type Func (F1 : Field) (F2 : Field).
Parameter eval : F1.T -> F2.T.
End Func.
Module FuncField (F1 : Field) (F2 : Field) (F : Func F1 F2).
Definition eval a := F.eval a.
Definition add a b := F2.add (F.eval a) (F.eval b).
Definition mul a b := F2.mul (F.eval a) (F.eval b).
End FuncField.
答案 0 :(得分:3)
功能键是各个模块之间的功能。从模块类型到模块类型都没有函子,但您可以作弊。 :)
与Coq不同,OCaml的模块不是完全依赖的类型,但在这种情况下它们“足够依赖”。 这个想法是模块可以包含模块类型。由于我们不能直接返回模块类型,因此我们只返回包含一个模块的模块!
您的示例变成这样:
module type Field = sig
type t
val add : t -> t -> t
val mul : t -> t -> t
end
module Func (F1 : Field) (F2 : Field) = struct
module type T = sig
val eval : F1.t -> F2.t
end
end
module FuncField (F1 : Field) (F2 : Field) (F : Func(F1)(F2).T) = struct
let eval a = F.eval a
let add a b = F2.add (F.eval a) (F.eval b)
let mul a b = F2.mul (F.eval a) (F.eval b)
end
请注意Func(F1)(F2).T
语法,该语法表示“应用函子,并从结果中获取模块类型T
”。 functor应用程序+字段访问的这种组合仅在类型(普通类型或模块类型)中可用。
我不记得我是在哪里找到这个技巧的,但是您可以在tyxml(definition,usage)的“生产中”操作中看到它。
答案 1 :(得分:1)
稍微走开框框,因为似乎您真的不需要仿函数来完成所描述的内容。简单的模块约束就足够了:
module type Field =
sig
type t
val add : t -> t -> t
val mul : t -> t -> t
end
module type Func =
sig
type t1
type t2
val eval : t1 -> t2
end
module FuncField (F1 : Field) (F2 : Field) (F : Func with type t1 = F1.t and type t2 = F2.t) =
struct
let eval a = F.eval a
let add a b = F2.add (F.eval a) (F.eval b)
let mul a b = F2.mul (F.eval a) (F.eval b)
end