Skip to content

Commit 03a02de

Browse files
authored
Merge pull request #9840 from dotty-staging/add-typeable
Add Typeable test
2 parents cad5cc9 + ffc9e17 commit 03a02de

File tree

2 files changed

+65
-0
lines changed

2 files changed

+65
-0
lines changed

tests/run/Typeable.check

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
1 is a Int
2+
List(1, 2, 3) is a List[Int]
3+
List(1, 2, 3) is not a Int
4+
1 is not a List[Int]
5+
a is not a Int
6+
List() is a List[Int]
7+
List(1, a) is not a List[Int]
8+
List(1, 2) is a List[Int]

tests/run/Typeable.scala

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/** A test that shows how to use shapeless.Typeable in extractors without the
2+
* TypeLevel Scala 4 extensions.
3+
* In essence you have to write
4+
*
5+
* case Typeable.instanceOf[T](x) =>
6+
*
7+
* instead of
8+
*
9+
* case Typeable[T](x)
10+
*
11+
* The first idiom would be nice to have but it requires more backtracking
12+
* in Typer that we allow now. Essentially, given
13+
*
14+
* case C[T](x)
15+
*
16+
* it's unclear whether this should expand to `C[T].unapply(x)`, (as it does now)
17+
* or to `C.unapply[T](x)` (which is what TypeLevel Scala 4 did, I believe)
18+
*/
19+
trait Typeable[T]:
20+
def cast(x: Any): Option[T]
21+
def describe: String
22+
override def toString = s"Typeable[$describe]"
23+
24+
object Typeable:
25+
def apply[T: Typeable]: Typeable[T] = summon
26+
27+
class instanceOf[T: Typeable]:
28+
def unapply(x: Any): Option[T] = Typeable[T].cast(x)
29+
30+
given int as Typeable[Int]:
31+
def cast(x: Any): Option[Int] = x match
32+
case x: Int => Some(x)
33+
case _ => None
34+
def describe = "Int"
35+
36+
given list[T: Typeable] as Typeable[List[T]]:
37+
def cast(x: Any): Option[List[T]] = x match
38+
case x: List[_] if x.forall(Typeable[T].cast(_).isDefined) => Some(x.asInstanceOf[List[T]])
39+
case _ => None
40+
def describe = s"List[${Typeable[T].describe}]"
41+
end Typeable
42+
43+
def testInstance[T: Typeable](x: Any): Unit =
44+
val isa = x match
45+
case Typeable.instanceOf[T](x) => "is a"
46+
case _ => "is not a"
47+
println(s"$x $isa ${Typeable[T].describe}")
48+
49+
@main def Test() =
50+
testInstance[Int](1)
51+
testInstance[List[Int]](List(1, 2, 3))
52+
testInstance[Int](List(1, 2, 3))
53+
testInstance[List[Int]](1)
54+
testInstance[Int]("a")
55+
testInstance[List[Int]](Nil)
56+
testInstance[List[Int]](1 :: "a" :: Nil)
57+
testInstance[List[Int]](1 :: 2 :: Nil)

0 commit comments

Comments
 (0)