-
-
Save jseteny/99fd53fa938482a77ec4bfb75a5b7ca0 to your computer and use it in GitHub Desktop.
Simple example of an IO effect Monad, no Cats, no ZIO
This file contains hidden or 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 scala.util.Random | |
// Simple example of an IO effect Monad, no Cats | |
object MyIO extends App{ | |
// IO encapsulates a side effecting operation | |
final class IO[A](val run: () => A) { | |
def map[B](f: A => B): IO[B] = IO(f(run())) | |
def flatMap[B](f: A => IO[B]): IO[B] = IO(f(run()).run()) | |
} | |
object IO { | |
def apply[A](a: =>A): IO[A] = new IO(() => a) | |
} | |
// Some example type classes, without regard to context | |
trait Console[C[_]] { | |
def read: C[String] | |
def readBoolean: C[Boolean] | |
def write(st: String): C[Unit] | |
} | |
trait Random[C[_]] { | |
def randomString: C[String] | |
} | |
// we implement IOs for above type classes, which is where we perform our side effects | |
object ConsoleIO extends Console[IO] { | |
def read: IO[String] = IO { io.StdIn.readLine } | |
def readBoolean: IO[Boolean] = IO { io.StdIn.readBoolean } | |
def write(st: String): IO[Unit] = IO { println(st) } | |
} | |
object RandomIO extends Random[IO] { | |
def randomString: IO[String]= IO {Random.alphanumeric.take(8).mkString} | |
} | |
// composing an IO with for comprehensions | |
def prog(consoleIO: Console[IO], randomIO: Random[IO]): IO[String] ={ | |
import consoleIO._ | |
import randomIO._ | |
println("running"*10) | |
for { | |
_<- write("please enter a word") | |
readWord <- read.map(_+" !!!") | |
_<- write("do you like cats?") | |
boolean <- readBoolean | |
randomString1 <- randomString | |
randomString2 <- randomString | |
str=s"$readWord,$boolean,$randomString1,$randomString2" | |
_<- write(str) | |
} yield str | |
} | |
println("Nothing is run yet, running now") | |
val out=prog(ConsoleIO,RandomIO).run() | |
println(s"out=$out") | |
object FakeConsoleIO extends Console[IO] { | |
def read: IO[String] = IO { "fake" } | |
def readBoolean: IO[Boolean] = IO { true } | |
def write(st: String): IO[Unit] = IO { () } | |
} | |
object FakeRandomIO extends Random[IO] { | |
def randomString: IO[String]= IO {"fakefake"} | |
} | |
// here we run again but with canned IOs, nothing comes from real console or real random source | |
val out2=prog(FakeConsoleIO,FakeRandomIO).run() | |
println(s"out2=$out2") | |
// we create 2 random numbers here, and output them | |
val rnd: IO[Unit] =for { | |
randomString1 <- RandomIO.randomString | |
randomString2 <- RandomIO.randomString | |
str=s"$randomString1,$randomString2" | |
_<- ConsoleIO.write(str) | |
} yield () | |
// note, both runs create different numbers, nothing is memoized | |
rnd.run() | |
rnd.run() | |
} |
This file contains hidden or 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
Nothing is run yet, running now | |
runningrunningrunningrunningrunningrunningrunningrunningrunningrunning | |
please enter a word | |
woof | |
do you like cats? | |
n | |
woof !!!,false,MisEM4ds,qkdC6hIR | |
out=woof !!!,false,MisEM4ds,qkdC6hIR | |
runningrunningrunningrunningrunningrunningrunningrunningrunningrunning | |
out2=fake !!!,true,fakefake,fakefake | |
qOA3J11v,pNhxfc2o | |
igrcGfC9,YizkSMkv |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment