-
Notifications
You must be signed in to change notification settings - Fork 1
/
GetTc.scala
96 lines (73 loc) · 2.28 KB
/
GetTc.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
package mylib.pattern
trait GetTc[Name <: TcHolder, ResultTc[A]] {
implicit def equiv[A]: ResultTc[A] =:= Name#Tc[A]
object reverse {
implicit final def eqReverse[A]: Name#Tc[A] =:= ResultTc[A] = {
equiv[A].asInstanceOf[Name#Tc[A] =:= ResultTc[A]]
}
}
}
trait GetTc1[Name <: TcHolder1, ResultTc[F[_]]] {
implicit def equiv[F[_]]: ResultTc[F] =:= Name#Tc[F]
object reverse {
implicit final def eqReverse[F[_]]: Name#Tc[F] =:= ResultTc[F] = {
equiv[F].asInstanceOf[Name#Tc[F] =:= ResultTc[F]]
}
}
}
trait TcHolder {
type Tc[_]
}
trait TcHolder1 {
type Tc[_[_]]
}
sealed trait CatsFunctor extends TcHolder1 {
override type Tc[F[_]] = cats.Functor[F]
}
object CatsFunctor {
@inline implicit final def get: GetTc1[CatsFunctor, cats.Functor] = {
new GetTc1[CatsFunctor, cats.Functor] {
override def equiv[F[_]] = implicitly
}
}
}
sealed trait CatsMonadTc extends TcHolder1 {
type Tc[F[_]] = cats.Monad[F]
}
object CatsMonadTc {
@inline implicit final def get: GetTc1[CatsMonadTc, cats.Monad] = new GetTc1[CatsMonadTc, cats.Monad] {
override def equiv[F[_]] = implicitly
}
}
final case class MyBox[A](get: A)
object MyBox {
implicit val myMonadForMyBox: MyMonad[MyBox] = new MyMonad[MyBox] {
override def pure[A](a: A): MyBox[A] = MyBox(a)
override def flatMap[A, B](fa: MyBox[A])(f: A => MyBox[B]): MyBox[B] = f(fa.get)
}
implicit def optionalCatsFunctorForMyBox[F[_[_]]](implicit ev: GetTc1[CatsFunctor, F]): F[MyBox] = {
import ev.reverse._
new cats.Functor[MyBox] {
def map[A, B](fa: MyBox[A])(f: A => B): MyBox[B] =
MyBox(f(fa.get))
}
}
}
trait MyMonad[F[_]] {
def pure[A](a: A): F[A]
def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B]
}
object MyMonad {
def apply[F[_]: MyMonad]: MyMonad[F] = implicitly
implicit def myMonadForList: MyMonad[List] = new MyMonad[List] {
def pure[A](a: A): List[A] = List(a)
def flatMap[A, B](fa: List[A])(f: A => List[B]): List[B] = fa.flatMap(f)
}
implicit def optionalMyMonadFromCatsMonad[F[_], M[_[_]]](implicit ev: GetTc1[CatsMonadTc, M], F: M[F]): MyMonad[F] = {
import ev._
new MyMonad[F] {
override def pure[A](a: A): F[A] = F.pure(a)
override def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B] = F.flatMap(fa)(f)
}
}
}