0
module St = begin
  type state 's ;;
  type st 's 'a = St of state 's -> (state 's * 'a) ;;

  external val run : (forall 's. st 's 'a) -> 'a = "(function(k) return k({ var = 0 })['2'] end)" ;;

  let fmap f (St k) =
    let go st =
      match k st with
      | (st, x) -> (st, f x)
    in St go
  and ap (St f) (St x) =
    let go st =
      match f st with
      | (st, f) -> match x st with
      | (st, x) -> (st, f x)
    in St go
  and bind (St x) f =
    let go st =
      match x st with
      | (st, x) -> match f x with
      | St k -> k st
    in St go
  and pure x = St (fun s -> (s, x)) ;;

  type ref 's 'a ;;

  external val update_state : ('a -> 'a) -> string -> state 's -> state 's * 'a =
    "(function(f, x, s) s[x] = f(s[x]); return { ['1'] = s, ['2'] = s[x] } end)" ;;
  external val make_var : string -> state 's -> ref 's 'a = "(function(x, _) return x end)" ;;
  external val get_var : ref 's 'a -> state 's -> string = "(function(x, _) return x end)" ;;

  module Ref = begin
    let alloc_ref (x : 'a) =
      let place _ = x
      and go st =
        match update_state (fun x -> x) "var" st with
        | (st, var) -> match update_state place var st with
        | (st, _) -> match update_state (fun x -> x + 1) "var" st with
        | (st, _) -> (st, make_var var st)
      in St go
    and update_ref (r : ref 's 'a) (f : 'a -> 'a) : st 's () =
      let go (st : state 's) =
        match update_state f (get_var r st) st with
        | (st, var) -> (st, ())
      in St go
    and read_ref (r : ref 's 'a) : st 's 'a =
      let go st = update_state (fun x -> x) (get_var r st) st
      in St go
  end
end ;;

open St.Ref ;;

external val print : 'a -> unit = "print" ;;

let main =
  let action =
    St.bind (alloc_ref 123) (fun var ->
      St.bind (update_ref var (fun x -> x * 2)) (fun () ->
        read_ref var))
  and result = St.run action
  in print result