-
Notifications
You must be signed in to change notification settings - Fork 1
/
Profunctor.scala
62 lines (52 loc) · 1.61 KB
/
Profunctor.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
package Triglav.face2
trait Profunctor[P[-_, +_]] extends Joker[P] with Bard[P] {
def dimap[S, T, A, B](pab: P[A, B])(sa: S => A, bt: B => T): P[S, T]
override def map[A, B, T](fa: P[A, B])(f: B => T): P[A, T] =
dimap(fa)(identity, f)
override def contramap[A, AA, B](fa: P[A, B])(f: AA => A): P[AA, B] =
dimap(fa)(f, identity)
}
trait ProfunctorLaws[P[-_, +_]]
extends JokerLaws[P]
with BardLaws[P]
with Profunctor[P] {
// dimap id id == id
def dimapIdentity[A, B](p: P[A, B]): Boolean = {
// dimap(id, id)
// P[A,B] ================> P[A,B]
dimap(p)(identity[A], identity[B]) == p
}
// dimap (f . g) (h . i) == dimap g h . dimap f i
def dimapComposition[A, A2, A3, B, B2, B3](
pad: P[A, B],
g: A3 => A2,
f: A2 => A,
i: B => B2,
h: B2 => B3
): Boolean = {
// dimap A2=>A B=>B2
// P[A,B] ===================> F[A2,B2]
val p2: P[A2, B2] = dimap(pad)(f, i)
// dimap A3=>A2 B2=>B3
// P[A2,B2] ====================> P[A3,B3]
val l: P[A3, B3] = dimap(p2)(g, h)
val fg: A3 => A = f compose g
val hi: B => B3 = h compose i
// dimap A3=>A B=>B3
// P[A,B] ===================> P[A3,B3]
val r: P[A3, B3] = dimap(pad)(fg, hi)
l == r
}
// dimap f g == contramap (map g) f
def dimapCoherentWithMapAndContramap[A, A2, A3, B, B2, B3](
pad: P[A, B],
f: A2 => A,
g: B => B2
): Boolean = {
// dimap A2=>A B=>B2
// P[A,B] ===================> F[A2,B2]
val l: P[A2, B2] = dimap(pad)(f, g)
val r = contramap(map(pad)(g))(f)
l == r
}
}