sta*_*man 5 monads ocaml haskell free-monad
我试图在ocaml中编写一个免费的monad库,跟随haskell的Control.Monad.Free,但是我在一个点上,在hoistFree的实现中陷入困境.
hoistFree :: Functor g => (forall a. f a -> g a) -> Free f b -> Free g b
hoistFree _ (Pure a) = Pure a
hoistFree f (Free as) = Free (hoistFree f <$> f as)
Run Code Online (Sandbox Code Playgroud)
这是我翻译的尝试.
let rec hoistfree : 'b.('b t -> 'b t) -> 'a m -> 'a m =
fun f x -> match x with
| Return x -> Return x
| Free x -> Free (T.map (hoistfree f) (f x));;
Run Code Online (Sandbox Code Playgroud)
不幸的是我收到一个错误,告诉我我没有正确扩大g的类型.
Error: This definition has type ('b m t -> 'b m t) -> 'b m -> 'b m
which is less general than 'a. ('a t -> 'a t) -> 'b m -> 'b m
Run Code Online (Sandbox Code Playgroud)
如果我不插入函数类型注释,一切正常,但随后如错误消息所示,我没有获得f的常规类型.问题出在哪儿?如何加宽f的类型?
我对 Ocaml 不太熟悉,但我相信
let rec hoistfree : 'b.('b t -> 'b t) -> 'a m -> 'a m =
Run Code Online (Sandbox Code Playgroud)
被解析为
let rec hoistfree : 'b. ( ('b t -> 'b t) -> 'a m -> 'a m ) =
Run Code Online (Sandbox Code Playgroud)
代替
let rec hoistfree : ('b. ('b t -> 'b t)) -> 'a m -> 'a m =
Run Code Online (Sandbox Code Playgroud)
前者是基本的多态类型,后者是Rank2类型,比Hindley-Milner需要更多类型系统的支持。
IIRC,要实现后者,您需要定义自定义包装数据类型。例如:
type poly = { polyf: 'a . 'a -> 'a } ;;
let foo (x: poly): int = x.polyf 4;;
let bar: poly = { polyf = fun x -> x } ;;
let _ = print_string ("hello " ^ string_of_int (foo bar));;
Run Code Online (Sandbox Code Playgroud)