Skip to content

Instantly share code, notes, and snippets.

@chirlo
Created April 30, 2014 15:59
Show Gist options
  • Save chirlo/05d5ec57cf8bccef78e6 to your computer and use it in GitHub Desktop.
Save chirlo/05d5ec57cf8bccef78e6 to your computer and use it in GitHub Desktop.
object ch6_new_state {
object State {
def unit[S, A](a: A): State[S, A] = State(s => (a, s))
def sequence[S, A](fs: List[State[S, A]]): State[S, List[A]] =
fs.foldRight(unit[S, List[A]](List[A]()))((x, y) => x.map2(y)(_ :: _))
def get[S]: State[S, S] = State(s => (s, s))
def set[S](s: S): State[S, Unit] = State(_ => ((), s))
def modify[S](f: S => S): State[S, Unit] = for {
s <- get
_ <- set(f(s))
} yield ()
}
case class State[S, +A](run: S => (A, S)) {
import State._
def flatMap[B](f: A => State[S, B]): State[S, B] = State(s => {
val (a, s1) = run(s)
f(a).run(s1)
})
def map[B](f: A => B): State[S, B] = flatMap(a => unit(f(a)))
def map2[B, C](sb: State[S, B])(f: (A, B) => C): State[S, C] =
for {
a <- this
b <- sb
} yield f(a, b)
}
sealed trait Input
case object Coin extends Input
case object Turn extends Input
case class Machine(locked: Boolean, candies: Int, coins: Int)
import State._
val dectab = Map[Input, PartialFunction[Machine, Machine]](
Coin -> {
case Machine(true, candies, coins) if candies != 0 => Machine(false, candies, coins + 1)
case m => m
},
Turn -> {
case Machine(false, candies, coins) if candies != 0 => Machine(true, candies - 1, coins)
case m => m
})
def simulateMachine(inputs: List[Input]): State[Machine, (Int, Int)] = {
val z = get[Machine].map(m => (m.candies, m.coins))
inputs.foldRight(z) { (i, acc) =>
modify(dectab(i)).map2(acc)((_, m) => m)
}
}
def simulateM2(inputs: List[Input]): State[Machine, (Int, Int)] =
for {
_ <- sequence(inputs.map(i => modify(dectab(i))))
x <- get
} yield (x.candies, x.coins)
val l = List(Coin, Turn, Coin, Turn)
val m = Machine(true, 2, 0)
simulateMachine(l).run(m)
simulateM2(l).run(m)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment