Skip to content

Instantly share code, notes, and snippets.

@caiorss
Forked from echeipesh/Reader.scala
Last active March 10, 2017 16:47
Show Gist options
  • Save caiorss/43ce7fb62bafa5995cc836b5a2744fbb to your computer and use it in GitHub Desktop.
Save caiorss/43ce7fb62bafa5995cc836b5a2744fbb to your computer and use it in GitHub Desktop.
Reader Monad
/// REPL Testing
//
// -----------------------------------------
$ scala
Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_20).
Type in expressions for evaluation. Or try :help.
scala> case class Reader[C, A](g: C => A) {
| def apply(c: C) = g(c)
|
| def map[B](f: A => B): Reader[C, B] = {
| Reader{ c => f(g(c)) }
| }
|
| def flatMap[B](f: A => Reader[C, B]): Reader[C, B] = {
| Reader{ c => f(g(c))(c) }
| }
| }
defined class Reader
scala> val r = Reader ((x: Int) => x + 10)
r: Reader[Int,Int] = Reader(<function1>)
scala> r.apply(10)
res0: Int = 20
scala> r.map(x => x * 3)
res1: Reader[Int,Int] = Reader(<function1>)
scala> r.map(x => x * 3).map( x => x + 5)
res2: Reader[Int,Int] = Reader(<function1>)
/// Map is Equivalent to function composition
scala> r.map(x => x * 3).apply(10)
res3: Int = 60
scala> r.map(x => x * 3).map(x => x + 5).apply(4)
res4: Int = 47
//-- flatMap is equivalent to Haskell bind
//
scala> r.flatMap(x => Reader(a => 10 * a + x)).apply(3)
res6: Int = 43
scala> r.flatMap(x => Reader(a => 10 * a + x)).apply(5)
res7: Int = 65
scala> r.flatMap(x => Reader(a => 10 * a + x)).apply(6)
res8: Int = 76
/// Create a monadic function
scala> val fn = (x: Int) => Reader((a: Int) => 10 * a + x)
fn: Int => Reader[Int,Int] = <function1>
scala> r.flatMap(fn)
res9: Reader[Int,Int] = Reader(<function1>)
scala> r.flatMap(fn).apply(3)
res10: Int = 43
scala> val fm = (x: Int) => Reader((a: Int) => 5 * a - 3 * x)
fm: Int => Reader[Int,Int] = <function1>
scala> r.flatMap(fn).flatMap(fm)
res11: Reader[Int,Int] = Reader(<function1>)
scala> r.flatMap(fn).flatMap(fm).apply(3)
res12: Int = -114
scala> r.flatMap(fn).flatMap(fm).apply(6)
res13: Int = -198
scala> r flatMap fn flatMap fm apply 6
res15: Int = -198
for {
a <- r
x <- fn(5)
y <- fm(6)
} yield (a + x + y)
scala> for {
| a <- r
| x <- fn(5)
| y <- fm(6)
| } yield (a + x + y)
res16: Reader[Int,Int] = Reader(<function1>)
val m = for {
a <- r
x <- fn(5)
y <- fm(6)
} yield (a + x + y)
scala> m
res17: Reader[Int,Int] = Reader(<function1>)
// a = r.apply(4) = 14
// x = fn(5).apply(4) = 45
// y = fm(6).apply(4) = 2
// a + x + y = 61 Ok.
//
scala> m.apply(4)
res18: Int = 61
scala> m.apply(5)
res19: Int = 77
case class Reader[C, A](g: C => A) {
def apply(c: C) = g(c)
def map[B](f: A => B): Reader[C, B] = {
Reader{ c => f(g(c)) }
}
def flatMap[B](f: A => Reader[C, B]): Reader[C, B] = {
Reader{ c => f(g(c))(c) }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment