在OCaml中增长monad类型

时间:2014-02-28 16:24:34

标签: types polymorphism ocaml

我对可组合状态monad的想法很感兴趣,并且计算行多态应该是实现它们的好方法。

这是我的代码:

module ObjectStateMonad =
  struct
    (* constrain state to objects *)
    type 'a state = < .. > as 'a

    (* A state monad yields tuple of a state-object and an observable value *)
    type ('a, 'b) monad = 'a state -> ('a state * 'b)

    (* usual bind, just more type parameters *)
    let bind : (('a, 'b) monad) -> ('b -> ('a, 'c) monad) -> ('a, 'c) monad = 
      fun m -> 
      fun f ->
      fun s ->
        let (st, obs) = m(s) in
        (f obs st)

    (* run, as usual *)
    let run m a = m(a)

    (* get does not directly expose the state but requires a "getter" *)
    let get f = 
      let m : 'a state -> ('a state * 'b) = fun s -> (s, f s)
      in m

    (* put requires a "setter" function to modify the state *)
    let put : ('a state * 'b -> 'a state) -> 'b -> ('a, unit) monad = 
      fun upd -> 
      fun b ->
      let m : 'a state -> ('a state * unit) = fun s -> 
    let s2 : 'a state = (upd (s,b)) in (s2, ()) 
      in m
  end

这个想法是从不同的来源组成状态monad并自动推断出组合状态的类型,所以当我定义两个getter时:

let get_count x = (x#get_count : int) ;; 
val get_count : < get_count : int; .. > -> int = <fun>                                                                                       

let get_length x = (x#get_length : int) ;; 
val get_length : < get_length : int; .. > -> int = <fun>         

我可以混合它们并获得组合状态的正确结果:

bind (get get_length) (fun _ -> get get_count) ;;
- : (< get_count : int; get_length : int; _.. >, int) ObjectStateMonad.monad = <fun>

不幸的是,它并不适用于放置部分:

let set_count (x,i) = x#set_count i ;;
val set_count : < set_count : 'a -> 'b; .. > * 'a -> 'b = <fun>

当我看看put时似乎有效:

 put set_count;;
- : '_a -> (< set_count : '_a -> 'b ObjectStateMonad.state; _.. > as 'b, unit) ObjectStateMonad.monad = <fun>

但是当我尝试bind结果时,发生了一些奇怪的

bind (put set_count 1) (get get_count) ;;
Error: ...

类型错误包含以下部分:

< set_count : int -> 'b ObjectStateMonad.state ObjectStateMonad.state;

状态类型增长。为什么会这样?

0 个答案:

没有答案