Last active
July 6, 2018 22:26
-
-
Save joshuakfarrar/9d3bd9aae50c3c777b7cb3ec137d8599 to your computer and use it in GitHub Desktop.
Implement FP in Scala exercise 6.11 using Cats' State Monad.
This file contains hidden or 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
name := "candy-machine" | |
version := "0.1" | |
scalaVersion := "2.12.6" | |
scalacOptions += "-Ypartial-unification" | |
libraryDependencies += "org.typelevel" %% "cats-core" % "1.0.1" |
This file contains hidden or 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
import cats.data.State | |
sealed trait Input | |
case object Coin extends Input | |
case object Turn extends Input | |
case class Machine(locked: Boolean, candies: Int, coins: Int) | |
object Main extends App { | |
val insertCoin: State[Machine, (Boolean, Int)] = State(machine => { | |
machine.candies match { | |
case n if n > 0 => (machine, (false, machine.coins + 1)) | |
case _ => (machine, (machine.locked, machine.coins)) | |
} | |
}) | |
val turn: State[Machine, (Boolean, Int)] = State(machine => { | |
machine.candies match { | |
case n if n > 0 => { | |
val candies = if (machine.locked) machine.candies else machine.candies - 1 | |
(machine, (true, candies)) | |
} | |
case _ => (machine, (machine.locked, machine.candies)) | |
} | |
}) | |
def act(input: Input): State[Machine, Machine] = State(machine => { | |
input match { | |
case Coin => { | |
val (locked, coins) = insertCoin.runA(machine).value | |
val m = machine.copy(locked = locked, coins = coins) | |
(m, m) | |
} | |
case Turn => { | |
val (locked, candies) = turn.runA(machine).value | |
val m = machine.copy(locked = locked, candies = candies) | |
(m, m) | |
} | |
} | |
}) | |
def simulateMachine(actions: List[Input]): State[Machine, (Int, Int)] = State(machine => { | |
val m = actions.foldLeft(machine)((m, input) => act(input).runA(m).value) | |
(m, (m.coins, m.candies)) | |
}) | |
val actions = List[Input]( | |
Coin, | |
Turn, | |
Turn, | |
Turn, | |
Turn, | |
Turn, | |
Coin, | |
Turn, | |
Turn, | |
Turn, | |
Turn, | |
Coin, | |
Coin, | |
Coin | |
) | |
val m = Machine(locked = true, candies = 5, coins = 10) | |
println(simulateMachine(actions).runA(m).value) // (15,3)! | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment