我对可组合状态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;
状态类型增长。为什么会这样?