Skip to content

Instantly share code, notes, and snippets.

@battermann
Created August 8, 2018 18:37
Show Gist options
  • Save battermann/c70de228b2e9218ad58fba906e541c02 to your computer and use it in GitHub Desktop.
Save battermann/c70de228b2e9218ad58fba906e541c02 to your computer and use it in GitHub Desktop.
reimplementation of the program from "FP to the Max" by John De Goes (https://www.youtube.com/watch?v=sxudIMiOo68) with PureApp (https://github.com/battermann/pureapp)
import $ivy.`com.github.battermann::pureapp:0.6.0`
import com.github.battermann.pureapp._
import com.github.battermann.pureapp.interpreters.Terminal._
import cats.effect.IO
import cats.implicits._
import scala.util.Try
object Main extends StandardPureApp[IO] {
// MODEL
sealed trait Msg
case object GameStarted extends Msg
final case class NameInput(name: String) extends Msg
final case class RndNumberGenerated(n: Int) extends Msg
final case class Guessed(input: String) extends Msg
final case class ContinueInput(input: String) extends Msg
case object Quit extends Msg
sealed trait Cmd
object Cmd {
case object None extends Cmd
final case class Prompt(text: String, msg: String => Msg) extends Cmd
final case class RandomInt(upper: Int, msg: Int => Msg) extends Cmd
final case class Output(text: String, msg: Msg) extends Cmd
}
final case class Model(name: String, number: Int)
def init: (Model, Cmd) =
(Model("", 0), Cmd.Prompt("What is your name?", NameInput))
def quit(msg: Msg): Boolean = msg == Quit
// UPDATE
def update(msg: Msg, model: Model): (Model, Cmd) =
msg match {
case GameStarted =>
(model, Cmd.RandomInt(5, RndNumberGenerated))
case NameInput(name) =>
(model.copy(name = name), Cmd.Output(s"Hello, $name, welcome to the game", GameStarted))
case RndNumberGenerated(n) =>
(model.copy(number = n + 1), Cmd.Prompt(s"Dear ${model.name}, please guess a number from 1 to 5:", Guessed))
case Guessed(input) =>
Try(input.toInt)
.fold(
_ => (model, Cmd.Prompt(s"That is not a valid selection, ${model.name}!\nDo you want to continue, ${model.name}", ContinueInput)),
guess =>
if (guess == model.number)
(model, Cmd.Prompt(s"You guessed right, ${model.name}!\nDo you want to continue, ${model.name}", ContinueInput))
else
(model,
Cmd.Prompt(s"You guessed wrong, ${model.name}! The number was ${model.number}\nDo you want to continue, ${model.name}?",
ContinueInput))
)
case ContinueInput(input) =>
input match {
case "y" => update(GameStarted, model)
case "n" => (model, Cmd.None)
case _ => (model, Cmd.Prompt(s"Do you want to continue, ${model.name}?", ContinueInput))
}
case Quit =>
(model, Cmd.None)
}
// IO
def nextInt(upper: Int): IO[Int] = IO(scala.util.Random.nextInt(upper))
def io(model: Model, cmd: Cmd): IO[Msg] =
cmd match {
case Cmd.None => Quit.pure[IO]
case Cmd.Output(text, msg) => putStrLn(text).as(msg)
case Cmd.Prompt(text, msg) => putStrLn(text).flatMap(_ => readLine.map(msg))
case Cmd.RandomInt(upper, msg) => nextInt(upper).map(msg)
}
}
Main.main(Array())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment