Module 如何声明一个模块实现了一个接口,使得签名中的一个类型与另一个类型相同?

Module 如何声明一个模块实现了一个接口,使得签名中的一个类型与另一个类型相同?,module,ocaml,functor,Module,Ocaml,Functor,我正在OCaml中创建单子,需要编写它们,所以我创建了变形金刚。我用身份monad在transformer中实现了常规monad: module type MONAD = sig type 'a m val (>>=) : 'a m -> ('a -> 'b m) -> 'b m val return : 'a -> 'a m end module Identity : MONAD = struct type 'a m = 'a let

我正在OCaml中创建单子,需要编写它们,所以我创建了变形金刚。我用身份monad在transformer中实现了常规monad:

module type MONAD = sig
  type 'a m
  val (>>=) : 'a m -> ('a -> 'b m) -> 'b m
  val return : 'a -> 'a m
end

module Identity : MONAD = struct
  type 'a m = 'a
  let (>>=) m f = f m
  let return x = x
end

module OptionT (M : MONAD) : MONAD with type 'a m := ('a option) M.m = struct
  type 'a m = ('a option) M.m
  let (>>=) m f = M.(>>=) m (fun option ->
    match option with
    | Some x -> f x
    | None -> M.return None)
  let return x = M.return @@ Some x
end

module Option = OptionT(Identity)
但是,我不能这样做:

open Option
let _ = (Some 1) >>= (fun x -> Some (x + 1))
错误是:

(Some 1)

This expression has type 'a option
    but an expression was expected of type 'b option Identity.m

Some (x + 1)

This expression has type 'a option
    but an expression was expected of type 'b option Identity.m
如果我试图用
module Identity:MONAD和'a m='a
类型修复错误,我会在
module Option=OptionT(Identity)
处得到一个错误,指出

The type `m' is required but not provided
现在看来,
'a
已经取代了签名中的
'a m

很好用

我如何告诉编译器模块实现了签名,以便签名中声明的类型与另一个类型相同,同时仍保留签名的原始类型声明

此表达式具有类型“a”选项,但表达式应为类型“b”选项标识。m

事实上,编译器对
标识
一无所知,只知道它的签名是
MONAD
。(
:MONAD
)不仅仅是帮助编译器的东西,它隐藏了有关
标识的所有信息,除了它的签名是
MONAD

因此,您可以为此添加类型相等

module Identity : MONAD with type 'a m = 'a = ...
它是有效的

此表达式具有类型“a”选项,但表达式应为类型“b”选项标识。m

事实上,编译器对
标识
一无所知,只知道它的签名是
MONAD
。(
:MONAD
)不仅仅是帮助编译器的东西,它隐藏了有关
标识的所有信息,除了它的签名是
MONAD

因此,您可以为此添加类型相等

module Identity : MONAD with type 'a m = 'a = ...
它是有效的

现在看来,签名中的“a”取代了“m”

这是破坏性替代的效果,当你写作时

module Identity : MONAD with type 'a m := 'a
您要求编译器将
'am
的所有实例替换为
'a
。 相反,带有
约束的标准
为模块类型添加了类型相等

 module Identity : MONAD with type 'a m = 'a
看看您的各种示例,您似乎混淆了这两者,并且在打算添加类型约束时使用了破坏性替换:

module OptionT(X:Monad) : MONAD with type 'a m = 'a = …
(* or *) module Option : MONAD with type 'a m = 'a option = …
而不是

module OptionT(X:Monad) : MONAD with type 'a m := 'a = …
(* nor *) module Option : MONAD with type 'a m := 'a option = …
现在看来,签名中的“a”取代了“m”

这是破坏性替代的效果,当你写作时

module Identity : MONAD with type 'a m := 'a
您要求编译器将
'am
的所有实例替换为
'a
。 相反,带有
约束的标准
为模块类型添加了类型相等

 module Identity : MONAD with type 'a m = 'a
看看您的各种示例,您似乎混淆了这两者,并且在打算添加类型约束时使用了破坏性替换:

module OptionT(X:Monad) : MONAD with type 'a m = 'a = …
(* or *) module Option : MONAD with type 'a m = 'a option = …
而不是

module OptionT(X:Monad) : MONAD with type 'a m := 'a = …
(* nor *) module Option : MONAD with type 'a m := 'a option = …

OP说他试过了,得到了
类型'm'是必需的,但没有提供
。OP说他试过了,得到了
类型'm'是必需的,但没有提供