type Color = Pink | Purple type Interactive<'R> = | Done of 'R | WhatColor of (Color -> Interactive<'R>) | WhatNumber of (int -> Interactive<'R>) let unitInt v = Done v let rec bindInt (f:'a -> Interactive<'b>) (comp:Interactive<'a>) = match comp with | Done v -> f v | WhatColor g -> WhatColor(fun c -> bindInt f (g c)) | WhatNumber g -> WhatNumber(fun c -> bindInt f (g c)) let getColor = WhatColor(fun c -> unitInt c) let getNumber = WhatNumber(fun n -> unitInt n) let demo = getColor |> bindInt (fun c1 -> getColor |> bindInt (fun c2 -> getNumber |> bindInt (fun n -> unitInt (List.init n (fun _ -> c1 = c2)) ))) let rec run c = match c with | Done v -> v | WhatNumber f -> let input = System.Console.ReadLine() run (f (int input)) | WhatColor f -> let input = System.Console.ReadLine() if input = "pink" then run (f Pink) elif input = "purple" then run (f Purple) else failwith "wrong input" //run demo |> printfn "Got %A" // -------------------------------------------------------------------------- (* module Haskell = type Question = type InteractiveSt<'S, 'R> = | Done of 'R | What of \exists 'Q such that 'Q is question. ('Q -> State<'S, 'R>) and State<'S, 'R> = St of ('S -> 'S * InteractiveSt<'S, 'R>) *) type InteractiveSt<'S, 'R> = | Done of 'R | WhatColor of (Color -> State<'S, 'R>) | WhatNumber of (int -> State<'S, 'R>) and State<'S, 'R> = St of ('S -> 'S * InteractiveSt<'S, 'R>) let unitSt v = St(fun s -> s, Done(v)) let rec bindSt (f:'a -> State<'s, 'b>) (comp:State<'s, 'a>) : State<'s, 'b> = St(fun s -> let (St g1) = comp let s, ia = g1 s match ia with | Done v -> let (St g2) = f v let (s, ib) = g2 s s, ib | WhatColor g -> s, WhatColor(fun c -> bindSt f (g c)) | WhatNumber g -> s, WhatNumber (fun n -> bindSt f (g n)) ) let getColorSt() = St(fun s -> s, WhatColor(fun c -> St(fun s -> s, Done(c)))) let getNumberSt() = St(fun s -> s, WhatNumber(fun n -> St(fun s -> s, Done(n)))) let getState() = St(fun s -> s, Done s) let setState ns = St(fun _ -> ns, Done ()) let demo2 : State = getState () |> bindSt (fun s -> getColorSt () |> bindSt (fun c1 -> getColorSt () |> bindSt (fun c2 -> getNumberSt () |> bindSt (fun n -> setState (c1::c2::s) |> bindSt (fun () -> unitSt (List.init n (fun _ -> c1 = c2)) ))))) let rec runSt (St c) s = match c s with | s, Done v -> s, v | s, WhatNumber f -> let input = System.Console.ReadLine() runSt (f (int input)) s | s, WhatColor f -> let input = System.Console.ReadLine() if input = "pink" then runSt (f (Pink)) s elif input = "purple" then runSt (f (Purple)) s else failwith "wrong input" runSt demo2 [Pink] |> printfn "Got %A"