Last active
January 31, 2017 15:31
-
-
Save r-wheeler/f6f5b9de113841578092360d94992d4d to your computer and use it in GitHub Desktop.
fp hang man
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 cats._ | |
import cats.data._ | |
import cats.implicits._ | |
trait IO[A]{self => | |
def run: A | |
def map[B](f: A =>B): IO[B] = { | |
new IO[B]{def run = f(self.run)} | |
} | |
def flatMap[B](f: A => IO[B]): IO[B] = { | |
new IO[B] {def run = f(self.run).run} | |
} | |
} | |
implicit object IO extends Monad[IO] { | |
def pure[A](a: A) = new IO[A] { | |
def run = a | |
} | |
def flatMap[A, B](fa: IO[A])(f: A => IO[B]) = fa.flatMap(f) | |
def apply[A](a: => A): IO[A] = pure(a) | |
def tailRecM[A, B](a: A)(f: A => IO[Either[A, B]]): IO[B] = { | |
flatMap(f(a)) { | |
case Right(b) => pure(b) | |
case Left(nextA) => tailRecM(nextA)(f) | |
} | |
} | |
} | |
def getLine(): IO[String] = { | |
IO{scala.io.StdIn.readLine()} | |
} | |
def putStrLn(s: String): IO[Unit]={ | |
IO{println(s)} | |
} | |
type Game[A] = StateT[IO,GameState, A] | |
sealed trait GameResult | |
final case object Won extends GameResult | |
final case object Lost extends GameResult | |
final case object InPlay extends GameResult | |
case class GameState( | |
theWord: String, | |
guesses: String, | |
lives: Int | |
) | |
implicit val gameShow: Show[GameState] = new Show[GameState]{ | |
def show(f: GameState) = { | |
val wordIndicator = f.theWord.map(x => if (f.guesses.contains(x)) x else " _ ").mkString("") | |
val usedIndicator = s"Guessed: ${f.guesses}" | |
val livesIndicator = s"Lives: ${f.lives}" | |
s"$wordIndicator, $usedIndicator, lives remaining: $livesIndicator" | |
} | |
} | |
def evalGame(gameState: GameState): GameResult = { gameState match { | |
case GameState(theWord, guesses, lives) if theWord.toSet.diff(guesses.toSet).isEmpty => Won | |
case GameState(theWord, guesses, lives) if lives < 1 => Lost | |
case _ => InPlay | |
} | |
} | |
val initState = GameState("apples","",10) | |
def liftIO[A](ioa: IO[A]) = StateT.lift[IO, GameState,A](ioa) | |
def runGame(): Game[Unit] = { | |
for { | |
in <- StateT.get[IO, GameState] | |
_ <- StateT.get[IO, GameState].flatMapF(faf => putStrLn(faf.show)) | |
_ <- liftIO(putStrLn(in.show)) | |
guess <- StateT.lift[IO,GameState,String](getLine) | |
_ <- liftIO(putStrLn(guess)) | |
updateLives = if (in.theWord.contains(guess)) (in.lives) else (in.lives -1) | |
newState = GameState(in.theWord,in.guesses ++ guess,updateLives) | |
_ <- liftIO(putStrLn(newState.show)) | |
_ <- StateT.set[IO,GameState](newState) | |
status = evalGame(newState) | |
_ <- status match { | |
case Won => liftIO(putStrLn("You Won!")) | |
case Lost => liftIO(putStrLn("You Lost!")) | |
case _ => runGame | |
} | |
/* | |
_ <- status match { | |
case Won => StateT.lift[IO,GameState,Unit](putStrLn("youWon")) | |
//case Lost => StateT.lift[IO,GameState,Unit](putStrLn("youLost")) | |
case _ => runGame | |
}*/ | |
} yield () | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment