forked from pchiusano/scalaz7-experimental
-
Notifications
You must be signed in to change notification settings - Fork 8
/
OptionT.scala
108 lines (83 loc) · 3.41 KB
/
OptionT.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
package scalaz
import std.option.optionInstance
/**
* OptionT monad transformer.
*/
final case class OptionT[F[_], A](runT: F[Option[A]]) {
self =>
def map[B](f: A => B)(implicit F: Functor[F]): OptionT[F, B] = new OptionT[F, B](
F.map(runT)(_ map f)
)
def flatMap[B](f: A => OptionT[F, B])(implicit F: Monad[F]): OptionT[F, B] = new OptionT[F, B](
F.bind(self.runT) {
case None => F.point(None: Option[B])
case Some(z) => f(z).runT
}
)
def flatMapF[B](f: A => F[B])(implicit F: Monad[F]): OptionT[F, B] = new OptionT[F, B](
F.bind(self.runT) {
case None => F.point(None: Option[B])
case Some(z) => F.map(f(z))(b => Some(b))
}
)
def ap[B](f: OptionT[F, A => B])(implicit F: Apply[F]): OptionT[F, B] =
OptionT(F.map2(f.runT, runT) {
case (ff, aa) => optionInstance.ap(aa)(ff)
})
}
//
// Prioritized Implicits for type class instances
//
trait OptionTInstances2 {
implicit def optionTFunctor[F[_]](implicit F0: Functor[F]): Functor[({type λ[α] = OptionT[F, α]})#λ] = new OptionTFunctor[F] {
implicit def F: Functor[F] = F0
}
}
trait OptionTInstances1 extends OptionTInstances2 {
implicit def optionTPointed[F[_]](implicit F0: Pointed[F]): Pointed[({type λ[α] = OptionT[F, α]})#λ] = new OptionTPointed[F] {
implicit def F: Pointed[F] = F0
}
}
trait OptionTInstances0 extends OptionTInstances1 {
implicit def optionTApply[F[_]](implicit F0: Apply[F]): Apply[({type λ[α] = OptionT[F, α]})#λ] = new OptionTApply[F] {
implicit def F: Apply[F] = F0
}
}
trait OptionTInstances extends OptionTInstances0 {
implicit def optionTMonadTrans: MonadTrans[OptionT] = new OptionTMonadTrans {}
implicit def optionTMonad[F[_]](implicit F0: Monad[F]): Monad[({type λ[α] = OptionT[F, α]})#λ] = new OptionTMonad[F] {
implicit def F: Monad[F] = F0
}
}
trait OptionTFunctions {
def optionT[M[_]] = new (({type λ[α] = M[Option[α]]})#λ ~> ({type λ[α] = OptionT[M, α]})#λ) {
def apply[A](a: M[Option[A]]) = new OptionT[M, A](a)
}
}
object OptionT extends OptionTFunctions with OptionTInstances
//
// Implementation traits for type class instances
//
private[scalaz] trait OptionTFunctor[F[_]] extends Functor[({type λ[α] = OptionT[F, α]})#λ] {
implicit def F: Functor[F]
override def map[A, B](fa: OptionT[F, A])(f: A => B): OptionT[F, B] = fa map f
}
private[scalaz] trait OptionTPointed[F[_]] extends Pointed[({type λ[α] = OptionT[F, α]})#λ] with OptionTFunctor[F] {
implicit def F: Pointed[F]
def point[A](a: => A): OptionT[F, A] = OptionT[F, A](F.point(Some(a)))
}
private[scalaz] trait OptionTApply[F[_]] extends Apply[({type λ[α] = OptionT[F, α]})#λ] with OptionTFunctor[F] {
implicit def F: Apply[F]
def ap[A, B](fa: OptionT[F, A])(f: OptionT[F, A => B]): OptionT[F, B] = fa ap f
}
private[scalaz] trait OptionTMonad[F[_]] extends Monad[({type λ[α] = OptionT[F, α]})#λ] with OptionTPointed[F] {
implicit def F: Monad[F]
def bind[A, B](fa: OptionT[F, A])(f: A => OptionT[F, B]): OptionT[F, B] = fa flatMap f
}
private[scalaz] trait OptionTMonadTrans extends MonadTrans[OptionT] {
def liftM[G[_], A](a: G[A])(implicit G: Monad[G]): OptionT[G, A] =
OptionT[G, A](G.map[A, Option[A]](a)((a: A) => Some(a)))
def hoist[M[_], N[_]](f: M ~> N) = new (({type f[x] = OptionT[M, x]})#f ~> ({type f[x] = OptionT[N, x]})#f) {
def apply[A](fa: OptionT[M, A]): OptionT[N, A] = OptionT(f.apply(fa.runT))
}
}