forked from markhibberd/introduction-to-fp-in-scala
-
Notifications
You must be signed in to change notification settings - Fork 5
/
ReaderT.scala
90 lines (80 loc) · 2.03 KB
/
ReaderT.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package patterns
import intro._
/*
* A reader data type in transformer form that represents the application of some
* environment to produce a value in some effect M.
*/
case class ReaderT[M[_], R, A](run: R => M[A]) {
/*
* Exercise 5.1:
*
* Implement map for ReaderT[M, R, A].
*
* The following laws must hold:
* 1) r.map(z => z) == r
* 2) r.map(z => f(g(z))) == r.map(g).map(f)
*
*/
def map[B](f: A => B)(implicit M: Monad[M]): ReaderT[M, R, B] =
???
/*
* Exercise 5.2:
*
* Implement flatMap (a.k.a. bind, a.k.a. >>=).
*
* The following law must hold:
* r.flatMap(f).flatMap(g) == r.flatMap(z => f(z).flatMap(g))
*
*/
def flatMap[B](f: A => ReaderT[M, R, B])(implicit M: Monad[M]): ReaderT[M, R, B] =
???
}
object ReaderT {
/*
* Exercise 5.3:
*
* Implement value (a.k.a. return, point, pure).
*
* Hint: Try using ReaderT constructor.
*/
def value[M[_]: Monad, R, A](a: => A): ReaderT[M, R, A] =
???
/*
* Exercise 5.4:
*
* Implement ask.
*
* Ask provides access to the current environment (R).
*
* Hint: Try using ReaderT constructor.
*/
def ask[M[_]: Monad, R]: ReaderT[M, R, R] =
???
/*
* Exercise 5.5:
*
* Implement local.
*
* Local produce a reader that runs with a modified environment.
*
* Hint: Try using ReaderT constructor.
*/
def local[M[_], R, A](f: R => R)(reader: ReaderT[M, R, A]): ReaderT[M, R, A] =
???
implicit def ReaderTMonad[F[_], R](implicit F: Monad[F]): Monad[ReaderT[F, R, ?]] =
new Monad[ReaderT[F, R, ?]] {
def point[A](a: => A) = ReaderT(_ => F.point(a))
def bind[A, B](a: ReaderT[F, R, A])(f: A => ReaderT[F, R, B]): ReaderT[F, R, B] = a flatMap f
}
/*
* Exercise 5.6:
*
* Implement monad trans instance.
*
* Hint: Try using ReaderT constructor.
*/
implicit def ReaderTMonadTrans[R]: MonadTrans[ReaderT[?[_], R, ?]] = new MonadTrans[ReaderT[?[_], R, ?]] {
def liftM[M[_]: Monad, A](ga: M[A]): ReaderT[M, R, A] =
???
}
}