private fun checkContinue ( name : String ?): IO < Boolean > = IO . monad (). binding { putStrLn ( "Do you want to continue, $name?" ). bind () ( getStrLn ()). map { it . toLowerCase () }. map { (1) when ( it ) { "y" -> true . liftIO () "n" -> false . liftIO () else -> checkContinue ( name ) } }. flatten () . bind () }. fix () private fun gameLoop ( name : String ?): IO < Unit > = IO . monad (). binding { putStrLn ( "Dear $name, please guess a number from 1 to 5:" ). bind () getStrLn (). safeToInt (). fold ( { putStrLn ( "You did not enter a number!" ). bind () }, { val number = nextInt ( 5 ). map { it + 1 }. bind () if ( it . bind () == number ) println ( "You guessed right, $name!" ) else putStrLn ( "You guessed wrong, $name! The number was $number" ). bind () } ) checkContinue ( name ). map { ( if ( it ) gameLoop ( name ) else Unit . liftIO ()) }. flatten () . bind () }. fix () private fun nextInt ( upper : Int ): IO < Int > = IO { random . nextInt ( upper ) } private fun IO < String >. safeToInt () = Try { map { it . toInt () }}