Last active
March 22, 2019 21:16
-
-
Save SegFaultAX/1d3b93090ebfd653f3d6ba74c594f988 to your computer and use it in GitHub Desktop.
Reader Monad [Scala]
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
object ReaderMonad extends App { | |
case class Reader[-E, +A](run: E => A) { | |
def map[B](fn: A => B): Reader[E, B] = | |
dimap((e: E) => e)(fn) | |
def contramap[E0](fn: E0 => E): Reader[E0, A] = | |
dimap(fn)(a => a) | |
def dimap[E0, B](f: E0 => E)(g: A => B): Reader[E0, B] = | |
Reader(e0 => g(run(f(e0)))) | |
def map2[EE <: E, B, C](r: Reader[EE, B])(fn: (A, B) => C): Reader[EE, C] = | |
Reader(e => fn(run(e), r.run(e))) | |
def flatMap[EE <: E, B](fn: A => Reader[EE, B]): Reader[EE, B] = | |
Reader(e => fn(run(e)).run(e)) | |
} | |
object Reader { | |
def unit[E, A](a: A): Reader[E, A] = | |
Reader(_ => a) | |
def ask[E]: Reader[E, E] = | |
Reader(e => e) | |
def asks[E, A](fn: E => A): Reader[E, A] = | |
ask.map(fn) | |
def local[E, A](r: Reader[E, A])(fn: E => E): Reader[E, A] = | |
Reader(e => r.run(fn(e))) | |
def traverse[E, A, B](as: List[A])(fn: A => Reader[E, B]): Reader[E, List[B]] = | |
as.foldRight[Reader[E, List[B]]](unit(List()))((e, a) => fn(e).map2(a)(_ :: _)) | |
def sequence[E, A](rs: List[Reader[E, A]]): Reader[E, List[A]] = | |
traverse(rs)(a => a) | |
} | |
/* | |
import Reader._ | |
case class Person(name: String, age: Int) | |
val result: Reader[Person, String] = for { | |
name <- asks(_.name) // not able to infer `E = Person` | |
age <- asks(_.age) // not able to infer `E = Person` | |
} yield "$name is $age years old" | |
println(result.run(Person("Test", 31))) | |
*/ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment