Created
August 8, 2018 18:37
-
-
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)
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
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