Slide 1

Slide 1 text

42.type: Literal-based singleton types in Scala @folone @xeno_by @retronym @adriaanm @extempore2

Slide 2

Slide 2 text

About me: @folone likes types* *same reasons why @propensive does in his “Batshit crazy algebra with types” talk

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

Examples

Slide 5

Slide 5 text

1. Records

Slide 6

Slide 6 text

val book = ("author" ->> "Benjamin Pierce") :: ("title" ->> "TAPL") :: ("id" ->> 262162091) :: ("price" ->> 44.11) :: HNil ! scala> book("author") // Note the result type res0: String = Benjamin Pierce ! scala> book("id") // Note the result type res1: Int = 262162091

Slide 7

Slide 7 text

trait Assoc[K] { type V ; val v: V } defined trait Assoc ! def mkAssoc[K, V0](k: K,v0: V0): Assoc[k.type] { type V = V0 } = new Assoc[k.type] {type V = V0 ; val v = v0} mkAssoc: [K, V0](k: K, v: V0)Assoc[k.type]{type V = V0} ! def lookup[K](k: K) (implicit a: Assoc[k.type]): a.V = a.v lookup: [K](k: K)(implicit assoc: Assoc[k.type])assoc.V

Slide 8

Slide 8 text

> implicit def firstAssoc = mkAssoc(1, "Panda!") firstAssoc: Assoc[1.type]{type V = String} ! > implicit def ageAssoc = mkAssoc("Age", 3) ageAssoc: Assoc["Age".type]{type V = Int} ! > implicit def nmAssoc = mkAssoc(“Name", “Jane”) nmAssoc: Assoc["Name".type]{type V = String} scala> lookup(1) res0: String = Panda! scala> lookup("Age") res1: Int = 3 scala> lookup("Name") res2: String = Jane

Slide 9

Slide 9 text

2. Residue

Slide 10

Slide 10 text

case class Residue[N <: Int: SingleInhabitant](n: Long){ lhs => def +(rhs: Residue[N]): Residue[N] = Residue((lhs.n + rhs.n) % inhabitant[N]) }

Slide 11

Slide 11 text

scala> Residue[15](15) + Residue[13](20) :10: error: type mismatch; found : Residue[13.type] required: Residue[15.type] Residue[15](15) + Residue[13](20) ^ scala> Residue[13](15) + Residue[13](20) res1: Residue[13.type] = Residue(9)

Slide 12

Slide 12 text

3. Ranged

Slide 13

Slide 13 text

class Ranged[From <: Int : SingleInhabitant, To <: Int : SingleInhabitant] { def sample = { val rnd = new scala.util.Random val from = inhabitant[From] val to = inhabitant[To] (from + rnd.nextInt(to - from + 1)) } }

Slide 14

Slide 14 text

scala> val range = new Ranged[10, 20] range: Ranged[10.type,20.type] = Ranged@78c22d25 ! scala> range.sample res0: Int = 13 ! scala> range.sample res1: Int = 11

Slide 15

Slide 15 text

Consistency

Slide 16

Slide 16 text

Here’s what you can do in Scala scala> val x = "panda!" x: String = panda! ! scala> val t: x.type = x t: x.type = panda! ! scala> final val k = "panda!" k: String("panda!") = panda!

Slide 17

Slide 17 text

Here’s what you cannot scala> val t: "panda!".type = "panda!" :1: error: identifier expected but string literal found. val t: "panda!".type = "panda!" ^

Slide 18

Slide 18 text

scala> val t: "panda!".type = "panda!" t: "panda!".type = panda! With 42.type

Slide 19

Slide 19 text

scala> val x = 42 x: Int = 42 ! scala> val t: x.type = 42 :8: error: type mismatch; found : x.type (with underlying type Int) required: AnyRef val t: x.type = 42 ^ scala> val workaround = Witness(42) workaround: shapeless.Witness{type T = Int(42)} = fresh$macro$3$1@35b45d3f ! scala> val t: workaround.T = 42 t: workaround.T = 42 Even more

Slide 20

Slide 20 text

scala> val t: 42.type = 42 t: 42.type = 42 ! ! ! scala> val t: 42 = 42 t: 42.type = 42 Or even Solution with 42.type

Slide 21

Slide 21 text

42: Literal-based singleton types in Scala

Slide 22

Slide 22 text

SimpleType ::= Path ‘.’ type A singleton type is of the form p.type, where p is a path pointing to a value expected to conform to scala.AnyRef. Before

Slide 23

Slide 23 text

After | Literal [‘.’ type] SimpleType ::= Path ‘.’ type

Slide 24

Slide 24 text

4.

Slide 25

Slide 25 text

State of deptypes Scala “Scala vs Idris: Dependent Types, Now and in the Future”* *Edwin Brady & Miles Sabin, Strange Loop 2013

Slide 26

Slide 26 text

How can we make it better? Well, we can try. Scala + Z3

Slide 27

Slide 27 text

scala> import z3.scala._, z3.scala.dsl._ import z3.scala._ import z3.scala.dsl._

Slide 28

Slide 28 text

scala> findAll((x: Val[Int]) => x > 23 && x < 42).toList res0: List[Int] = List(24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41)

Slide 29

Slide 29 text

((x: Val[Int]) => x > 23 && x < 42)

Slide 30

Slide 30 text

((x: Int) => x > 23 && x < 42)

Slide 31

Slide 31 text

((x: Int) => x > 23 && x < 42).type

Slide 32

Slide 32 text

val magic: ((x: Int) => x > 23 && x < 42).type = 30

Slide 33

Slide 33 text

val magic: ((x: Int) => x > 23 && x < 42).type = 30 val x: 42 = 42 val x: ((x: Int) => x == 42).type = 42

Slide 34

Slide 34 text

val x: 42 = 42 val x: ((x: Int) => x == 42).type = 42 val x: Int = 42 val x: ((x: Int) => x).type = 42 val magic: ((x: Int) => x > 23 && x < 42).type = 30

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

bit.ly/42_type

Slide 37

Slide 37 text

this thing would not be possible without: @xeno_by, @retronym, @adriaanm, and initial impl by @paulp Scala Z3 bindings: LARA@EPFL Z3: Microsoft research slides, illustrations: @killnicole Credits:

Slide 38

Slide 38 text

No content

Slide 39

Slide 39 text

- Contributing to Scala compiler - Type-level programming - Working/hackertime at SoundCloud Ask me about: Thanks. Questions?