Last active
June 29, 2016 19:05
-
-
Save krishnabhargav/249f77d90ee1a47bebce5d7f3bb647bb to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type State<'S,'a> = 'S -> ('a * 'S) | |
module State = | |
let unit a : State<_,_> = fun s -> (a, s) | |
let map<'s,'a,'b> (f : 'a -> 'b) (r : State<'s,'a>) = | |
fun s -> | |
let a,next = r(s) | |
f(a), next | |
let map2<'s,'a,'b,'c> (f : 'a -> 'b -> 'c) (ra : State<'s,'a>) (rb : State<'s,'b>) = | |
fun s -> | |
let a, next = ra (s) | |
let b, next = rb (next) | |
(f a b), next | |
let sequence<'s,'a> (rs : State<'s,'a> list) : (State<'s, 'a list>) = | |
(fun s -> | |
List.fold (fun (c,st) r -> | |
let x, nxt = r st | |
(x::c, nxt)) ([],s) rs) | |
|> map (List.rev) | |
let bind<'s,'a,'b> (f : 'a -> State<'s,'b>) (r : State<'s,'a>) : State<'s,'b> = | |
fun s -> s |> r ||> f | |
module CandyDispenser = | |
type Input = | |
| Coin | |
| Turn | |
type Machine = { locked: bool; candies : int; coins: int} | |
(** RULES **) | |
(* | |
The rules of the machine are as follows: | |
Inserting a coin into a locked machine will cause it to unlock if there’s any candy left. | |
Turning the knob on an unlocked machine will cause it to dispense candy and become locked. | |
Turning the knob on a locked machine or inserting a coin into an unlocked machine does nothing. | |
A machine that’s out of candy ignores all inputs. | |
*) | |
let simulateMachine (inputs: Input list) : State<Machine, (int * int)> = | |
let handle input : State<Machine, (int*int)> = | |
fun m -> | |
match input with | |
| Input.Coin when m.candies > 0 -> | |
(m.candies, m.coins + 1), { m with locked = false; coins = m.coins + 1} | |
| Input.Turn when m.locked |> not -> | |
(m.candies - 1, m.coins), { m with locked = true; candies = m.candies - 1} | |
| _ -> | |
(m.candies, m.coins), m | |
let sequenced = | |
inputs | |
|> List.map (handle) | |
|> State.sequence | |
(sequenced |> State.map (List.head)) | |
//buy | |
let buy = [Input.Coin; Input.Turn] |> simulateMachine | |
let machine : CandyDispenser.Machine = { candies = 5; coins = 10; locked = true } | |
//let res, machine = machine |> CandyDispenser.buy | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment