Last active
November 1, 2022 23:58
-
-
Save isaacabraham/0849128cc72f26779d3bbd160a97114e to your computer and use it in GitHub Desktop.
F# port of the first half of John De Goes "FP to the max" (https://www.youtube.com/watch?v=sxudIMiOo68)
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
#load @".paket\load\net452\FSharpPlus.fsx" | |
open FSharpPlus | |
open System | |
[<AutoOpen>] | |
module rec IO = | |
let run (IO computation) = computation() | |
type IO<'T> = | |
| IO of (unit -> 'T) | |
static member (>>=) (x, f) = IO(fun () -> run x |> f |> run) | |
static member Return (x:'T) = IO(fun () -> x) | |
[<AutoOpen>] | |
module SideEffects = | |
let private r = Random() | |
let printLn text = IO (fun () -> printfn "%s" text) | |
let readLn() = IO(fun () -> Console.ReadLine()) | |
let random upper = IO(fun () -> r.Next(0, upper)) | |
let parseInt s = Int32.TryParse s |> function | true, x -> Some x | false, _ -> None | |
let rec checkContinue name = monad { | |
do! printLn ("Do you want to continue, " + name + "?") | |
let! answer = readLn() |> map String.toLower | |
return! | |
match answer with | |
| "y" -> IO.Return true | |
| "n" -> IO.Return false | |
| _ -> checkContinue name } | |
let rec gameLoop name = monad { | |
let! secret = random 5 |> map ((+) 1) | |
do! printLn ("Dear " + name + ", please guess a number from 1 to 5:") | |
let! input = readLn() | |
do! | |
match parseInt input with | |
| None -> printLn "You did not enter a number!" | |
| Some x when x = secret -> printLn ("You guessed right, " + name + "!") | |
| Some _ -> printLn (sprintf "You guessed wrong, %s! The number was: %d" name secret) | |
let! shouldContinue = checkContinue name | |
return! | |
if shouldContinue then gameLoop name | |
else IO.Return() } | |
let main = monad { | |
do! printLn "What is your name?" | |
let! name = readLn() | |
do! printLn ("Hello, " + name + " welcome to the game!") | |
do! gameLoop name | |
return() } | |
run main |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Here's my simplified version https://gist.github.com/gusty/3a9d654de320225e4a17d92049646160/revisions
Using FSharpPlus
tryParse
and theasync
monad.You probably know it already, you can use
async
instead ofio
(that's the reason why there's no IO monad in F#+).