Skip to content

Commit dcc3822

Browse files
committed
add more tests
1 parent e1a068a commit dcc3822

File tree

2 files changed

+89
-0
lines changed

2 files changed

+89
-0
lines changed

tests/patmat/gadt5.check

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
63: Pattern Match Exhaustivity: (Try3.VC(_, _), Try3.VN()), (Try3.VN(), Try3.VC(_, _))

tests/patmat/gadt5.scala

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
object Try1 {
2+
// type-level naturals
3+
sealed trait TNat
4+
sealed trait TZero extends TNat
5+
sealed trait TSucc[T] extends TNat
6+
7+
//reflect TNat at the value level; given n: Nat[T], n and T represent the same number.
8+
//This is what Haskellers call "singleton types" and took from Omega.
9+
// The point is that we can use such a number both at compile-time and at runtime,
10+
// but of course the runtime representation is not erased.
11+
//And this constrains the type argument of `Nat` to be of type `TNat` — though you could add bounds for it.
12+
13+
sealed trait Nat[+T]
14+
case class Zero() extends Nat[TZero]
15+
case class Succ[T](n: Nat[T]) extends Nat[TSucc[T]]
16+
17+
//We can index Vect with the types of value-level Nat, but this is a bit overkill. Still, no warnings.
18+
sealed trait Vect[N <: Nat[_], +T]
19+
case class VN[T]() extends Vect[Zero, T]
20+
case class VC[T, N <: Nat[_]](x: T, xs: Vect[N, T]) extends Vect[Succ[N], T]
21+
22+
object Test {
23+
def foo[N <: Nat[_], A, B](v1: Vect[N, A], v2: Vect[N, B]) =
24+
(v1, v2) match {
25+
case (VN(), VN()) => 1
26+
case (VC(x, xs), VC(y, ys)) => 2
27+
}
28+
}
29+
}
30+
31+
//Since we didn't need value-level numbers, let's drop them:
32+
object Try2 {
33+
sealed trait TNat
34+
sealed trait TZero extends TNat
35+
sealed trait TSucc[T] extends TNat
36+
37+
sealed trait Vect[N <: TNat, +T]
38+
case class VN[T]() extends Vect[TZero, T]
39+
case class VC[T, N <: TNat](x: T, xs: Vect[N, T]) extends Vect[TSucc[N], T]
40+
41+
object Test {
42+
def foo[N <: TNat, A, B](v1: Vect[N, A], v2: Vect[N, B]) =
43+
(v1, v2) match {
44+
case (VN(), VN()) => 1
45+
case (VC(x, xs), VC(y, ys)) => 2
46+
}
47+
}
48+
}
49+
50+
//Same as Try2, but now `Vect` is covariant in `N` so we get the warning you described.
51+
object Try3 {
52+
sealed trait TNat
53+
sealed trait TZero extends TNat
54+
sealed trait TSucc[T] extends TNat
55+
56+
sealed trait Vect[+N <: TNat, +T]
57+
case class VN[T]() extends Vect[TZero, T]
58+
case class VC[T, N <: TNat](x: T, xs: Vect[N, T]) extends Vect[TSucc[N], T]
59+
60+
object Test {
61+
def foo[N <: TNat, A, B](v1: Vect[N, A], v2: Vect[N, B]) =
62+
//Warnings expected here!
63+
(v1, v2) match {
64+
case (VN(), VN()) => 1
65+
case (VC(x, xs), VC(y, ys)) => 2
66+
}
67+
}
68+
}
69+
70+
//Same as Try3, but now `Vect` is invariant
71+
object Try4 {
72+
sealed trait TNat
73+
sealed trait TZero extends TNat
74+
sealed trait TSucc[T] extends TNat
75+
76+
sealed trait Vect[N <: TNat, +T]
77+
case class VN[T]() extends Vect[TZero, T]
78+
case class VC[T, N <: TNat](x: T, xs: Vect[N, T]) extends Vect[TSucc[N], T]
79+
80+
object Test {
81+
def foo[N <: TNat, A, B](v1: Vect[N, A], v2: Vect[N, B]) =
82+
//Warnings expected here!
83+
(v1, v2) match {
84+
case (VN(), VN()) => 1
85+
case (VC(x, xs), VC(y, ys)) => 2
86+
}
87+
}
88+
}

0 commit comments

Comments
 (0)