Skip to content

Instantly share code, notes, and snippets.

@ismagin
Last active April 11, 2017 07:05
Show Gist options
  • Save ismagin/cc0443a6b9de5fcc2fa45c8d5a7ec4f7 to your computer and use it in GitHub Desktop.
Save ismagin/cc0443a6b9de5fcc2fa45c8d5a7ec4f7 to your computer and use it in GitHub Desktop.
IO Example
package ex
object EP extends App {
trait IO[A] { self =>
def run(): A
def _map[B](f: A => B): IO[B] = new IO[B] { override def run(): B = f(self.run()) }
def _flatMap[B](f: A => IO[B]): IO[B] = new IO[B] { override def run(): B = f(self.run()).run() }
}
trait Monad[F[_]] {
def unit[A](a: => A): F[A]
def map[A, B](fa: F[A])(f: A => B): F[B]
def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B]
}
implicit val m = new Monad[IO] {
override def unit[A](a: => A): IO[A] = new IO[A] { override def run(): A = a }
override def map[A, B](fa: IO[A])(f: A => B): IO[B] = fa._map(f)
override def flatMap[A, B](fa: IO[A])(f: A => IO[B]): IO[B] = fa._flatMap(f)
}
implicit class MonadOps[F[_], A](fa: F[A]) {
def flatMap[B](f: A => F[B])(implicit c: Monad[F]): F[B] = c.flatMap(fa)(f)
def map[B](f: A => B)(implicit c: Monad[F]): F[B] = c.map(fa)(f)
}
def out(s: String) = new IO[Unit] {
override def run(): Unit = println(s)
}
def in() = new IO[String] {
override def run(): String = scala.io.StdIn.readLine()
}
val program: IO[String] = for {
_ <- out("what is your name?")
name <- in()
_ <- out(s"hello $name")
} yield name
def doWhile[F[_], A](a: F[A])(cond: A => F[Boolean])(implicit c: Monad[F]): F[Unit] =
for {
a1 <- a
ok <- cond(a1)
_ <- if (ok) doWhile(a)(cond) else c.unit(())
} yield ()
def forever[F[_], A, B](a: F[A])(implicit c: Monad[F]): F[B] = {
lazy val t: F[B] = forever(a)
c.flatMap(a)(_ => t)
}
val program2: IO[Unit] = forever(program)
program2.run()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment