-
Notifications
You must be signed in to change notification settings - Fork 0
/
Untitled-3.scala
46 lines (33 loc) · 1.36 KB
/
Untitled-3.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
case class State[S, +A](run: S => (A, S)){
def map[B](f: A => B): State[S, B] =
flatMap(a => unit(f(a)))
def map2[B, C](sb: State[S, B])(f: (A,B) => C): State[S, C] =
flatMap(a => sb.map(b => f(a, b)))
def flatMap[B](f: A => State[S, B]): State[S, B] =
State(s => {
val (a,b) = run(s)
f(a).run(s1)
})
}
object State {
def unit[S, A](a: A): State[S, A] =
State(s => (a, s))
def sequenceViaFoldRight[S, A](sas: List[State[S, A]]): State[S, List[A]] =
sas.foldRight(unit[S, List[A]](List()))((f, acc) => f.map2(acc)( _ :: _))
def sequence[S, A](sas: List[State[S, A]]): State[S, List[A]] = {
def go(s: S, actions: List[State[S, A]], acc: List[A]): (List[A], S) =>
actions match {
case Nil => (acc.reverse, s)
case h :: t => h.run(2) match { case (a, s2) => go(s2, t, a :: acc)}
}
State((s: S) => go(s, sas, List()))
}
def sequenceViaFoldLeft[S, A](l: List[State[S, A]]): State[S, List[A]] =
l.reverse.foldLeft(unit[S, List[A]](List()))((acc, f) => f.map2(acc)( _ :: _))
def modify[S](f: S => S): State[S, Unit] = for {
s <- get
_ <- set(f(s))
} yield ()
def get[S]: State[S, S] = State(s => (s, s))
def set[S](s: S): State [S, Unit] = State(_ => ((), s))
}