如何将模块映射到OCaml中的模块类型?
我想定义一个依赖于其他模块的模块类型。我想我可以用一个函子,但我相信函子只是从模块到模块的映射,不可能用它们来定义从模块到模块类型的映射 下面是我想做的一个例子:如何将模块映射到OCaml中的模块类型?,ocaml,Ocaml,我想定义一个依赖于其他模块的模块类型。我想我可以用一个函子,但我相信函子只是从模块到模块的映射,不可能用它们来定义从模块到模块类型的映射 下面是我想做的一个例子: 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 -&g
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
我有一个字段
模块类型,比如实数和有理数,我想定义从一个字段到另一个字段的函数类型Func
,对于任意两个给定模块F1
,F2
。有了这些模块类型,我就可以定义FuncField
,它采用F1
、F2
、F
,基本上用add
和mul
来扩充F.eval
当我运行代码时,我在定义Func
的行中得到一个通用的错误:语法错误。有没有办法在OCaml中定义类似的内容
我不确定这是否需要依赖类型,但我对具有依赖类型的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.
函子是从一个模块到另一个模块的函数。从模块类型到模块类型之间没有函子。。。。但是你可以作弊
与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(,)中看到它在“生产”中的作用。有点超出了框架,因为看起来你并不真的需要一个函子来完成你所描述的。简单的模块约束可能就足够了:
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
那是个聪明的把戏。不过,我在实例化模块时遇到了麻烦。这没有编译(不幸的是,这可能会将其全部折叠为一行):模块FloatField:Field=struct type t=float让我们添加一个b=a+。b设mul a b=a*。b端模块MulByTwo=struct let eval a=2.0*。一个终端模块MulByTwoField=FuncField(FloatField)(FloatField)(MulByTwo),这仅仅是因为约束FloatField:Field
隐藏了FloatField.t=float
的事实。删除它,它就会编译。