PS

Path dependent type

Abstract type member

Scalaでは、abstract type memberとtype projectionを使ってtype family  (a \text{#} A) _ {a \in \mathbf{K} } を作ることができる。

object PathDepType {

    trait K {
        type A // abstract type member
    }

    trait a extends K {
        override type A = Int
    }

    trait b extends K {
        override type A = Char
    }

    implicitly[Int =:= a#A]
    implicitly[Char =:= b#A]

Path

Pathとは、大雑把に言うとvalueのidentifier、あるいはそれらを.で繋げたものである。 Method呼び出しが混ざっていてはいけない。

Pathのequality=は、Any.==は使用されず、以下から帰納的に決められる(と思う)。

  1. x = x
  2. y: x.type ならば、x = y

Singleton type member

Scalaは組み込みのsingleton type familyとしてtypeというtype memberを提供しているが、引数がpathに制限されている。 つまり、

とすると、

  •  (x.\text{type}) _ {x \in P} = (\lbrace x \rbrace) _ x

Path dependent type family

Type family  (A _ a) _ a から次のようなdependent type familyを作れる:

  •  (A _ {x.\text{type} } ) _ x

これをpath dependent type family over  A と(でも)言う。 その適用結果をpath dependent typeという。

特に  (a \text{#} A) _ a の場合は

  •  (x.A) _ {x \in P} = (x.\text{type} \text{#} A ) _ x

を使うことが出来る。

    object c extends K {
        override type A = String
    }

    implicitly[c.A =:= c.type#A]
    implicitly[c.A =:= String]

Path dependent method

Return typeがpath dependent typeになっているmethodのことをpath dependent methodという(ことにする)。つまり、path dependent type familyのproductのこと。

    def id(x: AnyRef): x.type = x

    val s: String = id("hello")
}

機能的にはpolymorphic methodのようになっている。 実践的にはfunctional dependencyを実装するとき必要になると思われる。

参考文献

*1:今のところなんらかの理由でAnyRefのsubtypeでなくてはいけない