Slide 1

Slide 1 text

path 依存型って何?

Slide 2

Slide 2 text

.。oO(さっちゃんですよヾ(〃l _ l)ノ゙☆)

Slide 3

Slide 3 text

.。oO(さっちゃんですよヾ(〃l _ l)ノ゙☆) 好きな技術 : Erlang VM、Clojure 開發環境 : zsh、Nix、asdf、Emacs (Evil)、Vivaldi https://ja.mackerel.io を作ってゐます

Slide 4

Slide 4 text

今讀んでゐる本

Slide 5

Slide 5 text

Scala の path 依存型って何? 調べてみました!

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

class A { class B { def f(b: B): Unit = {} } def newB: B = new B() } val a1 = new A() val a2 = a1 val b1 = a1.newB val b2 = a2.newB b1.f(b1) b1.f(b2) ?

Slide 9

Slide 9 text

class A { class B { def f(b: B): Unit = {} } def newB: B = new B() } val a1 = new A() val a2 = a1 val b1 = a1.newB val b2 = a2.newB b1.f(b1) // OK b1.f(b2) // Found: Playground.a2.B // Required: Playground.a1.B

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

type selection x.L ↑ 變數 ↑ に依存 した型 type selection は名前的 (nominal)

Slide 12

Slide 12 text

type selection x.L subtyping of types

Slide 13

Slide 13 text

type selection x.L well-formed types

Slide 14

Slide 14 text

type selection x.L explanation

Slide 15

Slide 15 text

trait A { type B def f(b: B): Unit = {} } trait Ba trait Aa extends A { type B = Ba } val aa = new Aa {} aa.f(new Ba {}) // OK val aaa: A = aa aaa.f(new Ba {}) // Found: Object with Playground.Ba {...} // Required: Playground.aaa.B

Slide 16

Slide 16 text

path 依存型の使ひ所

Slide 17

Slide 17 text

異なる變數から生成された値を受け附けない class Store { class Item {} def getItem: Item = new Item def save(item: Item): Unit = {} } val store1 = new Store val item1 = store1.getItem val store2 = new Store val item2 = store2.getItem store1.save(item1) // OK store1.save(item2) // Found: (Playground.item2 : Playground.store2.Item) // Required: Playground.store1.Item

Slide 18

Slide 18 text

値を parameter として持つ型 case class Z(modulus: Int) { sealed class Modulus { val value = modulus } object Modulus { implicit val mod: Modulus = new Modulus() } } class IntMod[N <: Z#Modulus] private (val value: Long) extends AnyVal { def +(x: IntMod[N])(implicit m: N): IntMod[N] = value + x } object IntMod { import scala.language.implicitConversions implicit def longAsIntModN[N <: Z#Modulus](i: Long)(implicit modulus: N ): IntMod[N] = new IntMod[N](i % modulus.value) implicit def intModN2Long(a: IntMod[_]): Long = a.value } val z1 = Z(2) val z2 = Z(10) val i1z1 = 1: IntMod[z1.Modulus] val i2z1 = 3: IntMod[z1.Modulus] val i1z2 = 1: IntMod[z2.Modulus] val i2z2 = 3: IntMod[z2.Modulus] println(i1z1 + i2z1) // 0: IntMod[z1.Modulus] println(i1z2 + i2z2) // 4: IntMod[z2.Modulus] println(i1z1 + i2z2) // Found: (Playground.i2z2 : Playground.IntMod[Playground.z2.Modulus]) // Required: Playground.IntMod[Playground.z1.Modulus]

Slide 19

Slide 19 text

實行時に確定する値に依存する型 trait time_t_proto { type time_t } trait time_t_impl[U] extends time_t_proto { type time_t = U } case class Ptr[U](time: U) extends time_t_impl[U] trait Platform extends time_t_proto object PlatformI386 extends Platform with time_t_impl[Int] object PlatformX64 extends Platform with time_t_impl[Long] val arch = "x86_64" val platform: Platform = if arch == "i386" then PlatformI386 else if arch == "x86_64" then PlatformX64 else ??? def f(timer: Ptr[platform.time_t]): platform.time_t = timer.time val t = Ptr(42L.asInstanceOf[platform.time_t]) // C から渡される f(t) // 42: platform.time_t

Slide 20

Slide 20 text

dependent method と 依存函數型 (dependent function type)

Slide 21

Slide 21 text

dependent method method の引數變數に依存した型 trait V trait A { type B = V def newB = new B {} } def f(a: A): a.B = a.newB f(new A {}) // : V

Slide 22

Slide 22 text

依存函數型 (dependent function type) 引數變數に依存した函數型 trait A { type B; val b: B } val f: (a: A) => a.B = (a: A) => a.b

Slide 23

Slide 23 text

dependent method や依存函數型の使ひ所

Slide 24

Slide 24 text

總稱型 (generics) abstract class Key(name: String) { type Value } def key[V](name: String) = new Key(name) { override type Value = V } class DB { def set(k: Key, v: k.Value): Unit = {} } val db = new DB val k1 = key[String]("k1") val k2 = key[Double]("k2") db.set(k1, "v1") db.set(k2, 42.0) case class Key[V](name: String) {} class DB { def set[V](k: Key[V], v: V): Unit = {} } val db = new DB val k1 = Key[String]("k1") val k2 = Key[Double]("k2") db.set(k1, "v1") db.set(k2, 42.0)

Slide 25

Slide 25 text

條件分岐 object ApplyEither { def apply[T, F, G](t: T, f: F, g: G)(implicit ea: EApply[T, F, G]): ea.Out = ea(t, f, g) } trait EApply[T, F, G] { type Out def apply(t: T, f: F, g: G): Out } object EApply { def apply[T, F, G](implicit ea: EApply[T, F, G]) = ea implicit def applyF[T, R, G]: EApply[T, T => R, G] = new EApply[T, T => R, G] { type Out = R def apply(t: T, f: T => R, g: G) = f(t) } implicit def applyG[T, R, F]: EApply[T, F, T => R] = new EApply[T, F, T => R] { type Out = R def apply(t: T, f: F, g: T => R) = g(t) } } ApplyEither(1, { (x: Int) => 42 }, { (x: Double) => "no" }) // 42: EApply[Int, Function1[Int, Int], Function1[Double, String]].Out ApplyEither(2.0, { (x: Int) => 42 }, { (x: Double) => "no" }) // "no": EApply[Int, Function1[Int, Int], Function1[Double, String]].Out

Slide 26

Slide 26 text

いかがでしたか?

Slide 27

Slide 27 text

參考文獻 真理について〈2〉 (ヤスパース選集 ) | カール ヤスパース, Jaspers,Karl, 靖昌, 小林 |本 | 通販 | Amazon https://www.amazon.co.jp/dp/4650001323/ 内部クラス | Scala Documentation https://docs.scala-lang.org/ja/tour/inner-classes.html Nada Amin, Tiark Rompf, and Martin Odersky. 2014. Foundations of path-dependent types. SIGPLAN Not. 49, 10 (October 2014), 233–249. https://doi.org/10.1145/2714064.2660216 Path dependent types. Modeling algebraic structures has never… | by Marcin Rzeźnicki | VirtusLab | Medium https://medium.com/virtuslab/path-dependent-types-9f2d7927c1fa A quick explanation of Path Dependent Types - DEV Community https://dev.to/markehammons/a-quick-explanation-of-path-dependent-types-4pki Dependent Function Types | Scala 3 — Book | Scala Documentation https://docs.scala-lang.org/scala3/book/types-dependent-function.html Dependent Types in Scala - Some Tips, Tricks and Techniques https://wheaties.github.io/Presentations/Scala-Dep-Types/dependent-types.html