Skip to content

Commit d9d2982

Browse files
committed
Initial commit
0 parents  commit d9d2982

File tree

8 files changed

+114
-0
lines changed

8 files changed

+114
-0
lines changed

.gitignore

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Project exclude paths
2+
/project/project/target/
3+
/project/target/
4+
/target/
5+
/target/scala-3.4.0/classes/
6+
/target/scala-3.4.0/test-classes/

README.txt

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
* https://github.com/milessabin/strangeloop-2013/tree/master
2+
* ["Scala vs Idris: Dependent types, now and in the future" by Miles Sabin and Edwin Brady (2013)](https://www.youtube.com/watch?v=fV2no1Rkzdw)
3+
* https://github.com/mbovel/scalacon-typelevel-operations
4+
* [Type level Programming in Scala - Matt Bovel](https://www.youtube.com/watch?v=B7uficxARKM)

build.sbt

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
ThisBuild / version := "0.1.0-SNAPSHOT"
2+
3+
ThisBuild / scalaVersion := "3.4.0"
4+
5+
lazy val root = (project in file("."))
6+
.settings(
7+
name := "scala3-dependent-types-workshop"
8+
)
9+
10+
// Add ScalaCheck dependency
11+
libraryDependencies += "org.scalacheck" %% "scalacheck" % "1.17.0" % Test
12+
13+
// Optional: If you want to use ScalaTest as well
14+
libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.17" % Test

project/build.properties

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
sbt.version = 1.9.9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package workshop
2+
3+
object CompileTimeSizedVector {
4+
5+
}
+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package workshop
2+
3+
object SafeHead {
4+
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package workshop
2+
3+
import scala.compiletime.ops.int.{+}
4+
import scala.compiletime.ops.string.{CharAt, Length, Substring}
5+
6+
object TypeSafePrintf {
7+
8+
type ArgTypes[S <: String] <: Tuple = S match
9+
case "" => EmptyTuple
10+
case _ =>
11+
CharAt[S, 0] match
12+
case '%' =>
13+
CharAt[S, 1] match
14+
case 'd' => Int *: ArgTypes[Substring[S, 2, Length[S]]]
15+
case 's' => String *: ArgTypes[Substring[S, 2, Length[S]]]
16+
case _ => ArgTypes[Substring[S, 1, Length[S]]]
17+
18+
def printf(s: String)(t: ArgTypes[s.type]): Unit = ()
19+
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import org.scalacheck.Properties
2+
import org.scalacheck.Prop.forAll
3+
import org.scalatest.Assertions.{assertCompiles, assertDoesNotCompile}
4+
import org.scalatest.flatspec.AnyFlatSpec
5+
import org.scalatest.matchers.should.Matchers
6+
import workshop.TypeSafePrintf._
7+
8+
9+
object TypeSafePrintfPropertiesSpec extends Properties("TypeSafePrintf") {
10+
11+
property("supports %s %d format") = forAll { (s: String, i: Int) =>
12+
printf("%s is %d")(s, i)
13+
true
14+
}
15+
16+
property("support %d %s format") = forAll { (s: String, i: Int) =>
17+
printf("%d is %s")(i, s)
18+
true
19+
}
20+
}
21+
22+
class TypeSafePrintfSpec extends AnyFlatSpec with Matchers {
23+
24+
it should "represent %s %s as (String, String)" in {
25+
assertCompiles("summon[ArgTypes[\"%s %s\"] =:= (String, String)]")
26+
}
27+
28+
it should "represent %s %s %s as (String, String, String)" in {
29+
assertCompiles("summon[ArgTypes[\"%s %s %s\"] =:= (String, String, String)]")
30+
}
31+
32+
it should "represent %s %d as (String, Int)" in {
33+
assertCompiles("summon[ArgTypes[\"%s is %d\"] =:= (String, Int)]")
34+
}
35+
36+
it should "represent %d %s as (Int, String)" in {
37+
assertCompiles("summon[ArgTypes[\"%d is %s\"] =:= (Int, String)]")
38+
}
39+
40+
it should "compile %s %d format with correctly ordered params" in {
41+
assertCompiles("printf(\"%d is %s\")(5, \"a\")")
42+
}
43+
44+
it should "not compile %s %d format with wrong ordered params" in {
45+
assertDoesNotCompile("printf(\"%s %d\")(5, \"a\")")
46+
}
47+
48+
it should "not compile %d %s format with wrong ordered params" in {
49+
assertDoesNotCompile("printf(\"%d %s\")(\"a\", 5)")
50+
}
51+
52+
it should "not compile %d %s format with too many params" in {
53+
assertDoesNotCompile("printf(\"%s %d\")(\"a\", 5, 6)")
54+
}
55+
56+
it should "not compile %d %s format with too few params" in {
57+
assertDoesNotCompile("printf(\"%s %d\")(\"a\")")
58+
}
59+
}

0 commit comments

Comments
 (0)