如何声明一个模块实现了一个接口,使得签名中的类型与另一种类型相同?
How does one state that a module implements an interface so that a type in the signature is the same as another type?
我正在 OCaml 中创建 monad 并且需要组合它们,所以我创建了转换器。我根据带有 Identity monad 的转换器实现了常规 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 with type 'a m = 'a
修复错误,我会在 module Option = OptionT(Identity)
处收到一个错误,指出
The type `m' is required but not provided
现在看来,'a
已经替换了签名中的'a m
正在做
module Option : MONAD with type 'a m := 'a option = struct
type 'a m = 'a option
let (>>=) m f =
match m with
| Some x -> f x
| None -> None
let return x = Some x
end
工作正常。
如何告诉编译器一个模块实现了一个签名,以便签名中声明的类型与另一个类型相同,同时仍保留签名的原始类型声明?
This expression has type 'a option but an expression was expected of type 'b option Identity.m
事实上,编译器除了它的签名是MONAD
之外,对Identity
一无所知。 (: MONAD
) 不仅仅是帮助编译器,它隐藏了关于 Identity
的所有信息,除了它的签名是 MONAD
.
因此,您可以为此添加一个类型相等性
module Identity : MONAD with type 'a m = 'a = ...
而且有效。
It seems that now, 'a has replaced 'a m in the signature.
这是破坏性替换的效果,当你写
module Identity : MONAD with type 'a m := 'a
您要求编译器将 'a m
的所有实例替换为 'a
。
相反,标准 with
约束向模块类型
添加类型相等性
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 = …
我正在 OCaml 中创建 monad 并且需要组合它们,所以我创建了转换器。我根据带有 Identity monad 的转换器实现了常规 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 with type 'a m = 'a
修复错误,我会在 module Option = OptionT(Identity)
处收到一个错误,指出
The type `m' is required but not provided
现在看来,'a
已经替换了签名中的'a m
正在做
module Option : MONAD with type 'a m := 'a option = struct
type 'a m = 'a option
let (>>=) m f =
match m with
| Some x -> f x
| None -> None
let return x = Some x
end
工作正常。
如何告诉编译器一个模块实现了一个签名,以便签名中声明的类型与另一个类型相同,同时仍保留签名的原始类型声明?
This expression has type 'a option but an expression was expected of type 'b option Identity.m
事实上,编译器除了它的签名是MONAD
之外,对Identity
一无所知。 (: MONAD
) 不仅仅是帮助编译器,它隐藏了关于 Identity
的所有信息,除了它的签名是 MONAD
.
因此,您可以为此添加一个类型相等性
module Identity : MONAD with type 'a m = 'a = ...
而且有效。
It seems that now, 'a has replaced 'a m in the signature.
这是破坏性替换的效果,当你写
module Identity : MONAD with type 'a m := 'a
您要求编译器将 'a m
的所有实例替换为 'a
。
相反,标准 with
约束向模块类型
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 = …