forked from charleso/introduction-to-fp-in-scala
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathStateT.scala
111 lines (100 loc) · 2.3 KB
/
StateT.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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package patterns
import intro._
/*
* A state data type that represents the threading
* of some state value through computations in some effect M.
*/
case class StateT[M[_], S, A](run: S => M[(S, A)]) {
/*
* Exercise 7.1:
*
* Implement map for StateT[M, S, 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]): StateT[M, S, B] =
???
/*
* Exercise 7.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 => StateT[M, S, B])(implicit M: Monad[M]): StateT[M, S, B] =
???
}
object StateT {
/*
* Exercise 7.3:
*
* Implement value (a.k.a. return, point, pure).
*
* Hint: Try using StateT constructor.
*/
def value[M[_]: Monad, S, A](a: => A): StateT[M, S, A] =
???
/*
* Exercise 7.4:
*
* Implement get.
*
* Get provides access to the current state (S).
*
* Hint: Try using StateT constructor.
*/
def get[M[_]: Monad, S]: StateT[M, S, S] =
???
/*
* Exercise 7.5:
*
* Implement gets.
*
* Gets provides access to a view of the current state (S).
*
* Hint: Try building on get.
*/
def gets[M[_]: Monad, S, A](f: S => A): StateT[M, S, A] =
???
/*
* Exercise 7.6:
*
* Implement modify.
*
* Update the current state and produce no value.
*
* Hint: Try using State constructor.
*/
def modify[M[_]: Monad, S](f: S => S): StateT[M, S, Unit] =
???
/*
* Exercise 7.7:
*
* Implement put.
*
* Clobber the current state and produce no value.
*
* Hint: Try building on modify.
*/
def put[M[_]: Monad, S](s: S): StateT[M, S, Unit] =
???
implicit def StateTMonad[F[_], S](implicit F: Monad[F]): Monad[StateT[F, S, ?]] =
new Monad[StateT[F, S, ?]] {
def point[A](a: => A) = StateT(s => F.point((s, a)))
def bind[A, B](a: StateT[F, S, A])(f: A => StateT[F, S, B]) = a flatMap f
}
/*
* Exercise 7.8:
*
* Implement monad trans instance.
*
* Hint: Try using StateT constructor and Monad[M].map(ga).
*/
implicit def StateTMonadTrans[S]: MonadTrans[StateT[?[_], S, ?]] =
???
}