さっちゃん
November 24, 2023
330

# path 依存型って何?

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

## さっちゃん

November 24, 2023

## Transcript

3. ### .｡oO(さっちゃんですよヾ(〃l _ l)ﾉﾞ☆) 好きな技術 : Erlang VM、Clojure 開發環境 : zsh、Nix、asdf、Emacs

(Evil)、Vivaldi https://ja.mackerel.io を作ってゐます

6. ### 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) ?
7. ### 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
8. ### type selection x.L ↑ 變數 ↑ に依存 した型 type selection

は名前的 (nominal)

12. ### 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

14. ### 異なる變數から生成された値を受け附けない 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
15. ### 値を 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]
16. ### 實行時に確定する値に依存する型 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

18. ### 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
19. ### 依存函數型 (dependent function type) 引數變數に依存した函數型 trait A { type B;

val b: B } val f: (a: A) => a.B = (a: A) => a.b

21. ### 總稱型 (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)
22. ### 條件分岐 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

24. ### 參考文獻 真理について〈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