blob: 967472735eb66156b4b06c0c4b8e1bc0cd354c4f (
plain) (
blame)
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
|
trait Nat
case class S(x: Nat) extends Nat
case class Z() extends Nat
trait Sum[+S1, +S2]
case class Fst[+F](x: F) extends Sum[F, Nothing]
case class Snd[+S](x: S) extends Sum[Nothing, S]
trait shaped[SH1, SH2] {
def toShape(x: SH1): SH2
def fromShape(x: SH2): SH1
}
object Test {
type NatShape = Sum[Nat, Z]
implicit def natShape: Nat `shaped` NatShape =
new (Nat `shaped` NatShape) {
def toShape(n: Nat) = n match {
case S(m) => Fst(m)
case Z() => Snd(Z())
}
def fromShape(s: NatShape) = s match {
case Fst(n) => S(n)
case Snd(_) => Z()
}
}
trait Countable[T] {
def count(x: T): Int
}
implicit def ShapedCountable[T, U](implicit
ev1: T shaped U,
ev2: Countable[U]
): Countable[T] =
new Countable[T] {
def count(x: T) = ev2.count(ev1.toShape(x))
}
implicit def SumCountable[T, U](implicit
ev1: => Countable[T]
): Countable[Sum[T, U]] =
new Countable[Sum[T, U]] {
def count(s: Sum[T, U]) = s match {
case Fst(x) => ev1.count(x) + 1
case Snd(_) => 0
}
}
def count[T, U >: T](x: T)(implicit ev1: Countable[U]) = ev1.count(x)
def main(args: Array[String]) = {
println(
count(S(S(S(Z())))))
}
}
|