Last active
March 29, 2019 14:10
-
-
Save ffgiraldez/c2fb37d2a6a7a24df9d90d40864be404 to your computer and use it in GitHub Desktop.
FP to the Max on Arrow FX
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
package es.ffgiraldez.gist.arrow | |
import arrow.core.Option | |
import arrow.core.Try | |
import arrow.effects.extensions.io.fx.fx | |
import arrow.effects.extensions.io.unsafeRun.runBlocking | |
import arrow.unsafe | |
import java.util.Random | |
interface Console { | |
suspend fun putStrLn(s: String): Unit | |
suspend fun getStrLn(): String | |
} | |
object CommandLine : Console { | |
override suspend fun putStrLn(s: String) = println(s) | |
override suspend fun getStrLn(): String = readLine() ?: "" | |
} | |
interface Generator { | |
suspend fun nextInt(upper: Int): Int | |
} | |
object RandomGenerator : Generator { | |
private val random: Random = Random() | |
override suspend fun nextInt(upper: Int): Int = random.nextInt(upper) + 1 | |
} | |
class FpToTheMax( | |
private val console: Console, | |
private val generator: Generator | |
) { | |
fun program() = fx { | |
!effect { console.putStrLn("What is your name?") } | |
val name = !effect { console.getStrLn() } | |
!effect { console.putStrLn("your name is $name") } | |
!effect { gameLoop(name) } | |
} | |
private fun parseInt(s: String): Option<Int> = Try { s.toInt() }.toOption() | |
private suspend fun gameLoop(name: String) { | |
val num = generator.nextInt(5) | |
console.putStrLn("Dear $name, please guess a number from 1 to 5:") | |
val input = console.getStrLn() | |
parseInt(input).fold( | |
{ console.putStrLn("You did not enter a number") }, | |
{ guess -> | |
if (guess == num) console.putStrLn("You guessed right, $name!") | |
else console.putStrLn("You guessed wrong, $name! The number was: $num") | |
} | |
) | |
val cont = checkContinue(name) | |
return if (cont) gameLoop(name) | |
else Unit | |
} | |
private suspend fun checkContinue(name: String): Boolean { | |
console.putStrLn("Do you want to continue, $name?") | |
val input = console.getStrLn().toLowerCase() | |
return when (input) { | |
"y" -> true | |
"n" -> false | |
else -> checkContinue(name) | |
} | |
} | |
} | |
val FPInstance = FpToTheMax(CommandLine, RandomGenerator) | |
fun main(args: Array<String>) { | |
unsafe { runBlocking { FPInstance.program() } } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment