Skip to content

Instantly share code, notes, and snippets.

@isaacabraham
Last active November 1, 2022 23:58
Show Gist options
  • Save isaacabraham/0849128cc72f26779d3bbd160a97114e to your computer and use it in GitHub Desktop.
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)
#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
@giuliohome
Copy link

giuliohome commented Aug 17, 2018

@gusty
Copy link

gusty commented May 28, 2019

Here's my simplified version https://gist.github.com/gusty/3a9d654de320225e4a17d92049646160/revisions

Using FSharpPlus tryParse and the async monad.

You probably know it already, you can use async instead of io (that's the reason why there's no IO monad in F#+).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment