11

より高いkinded-typesでコンテキスト境界構文ショートカットを使用することは可能ですか?

trait One { def test[W   : ClassManifest]: Unit } // first-order ok
trait Two { def test[W[_]: ClassManifest]: Unit } // not possible??
trait Six { def test[W[_]](implicit m: ClassManifest[W[_]]): Unit } // hmm...
4

2 に答える 2

12

はい、そうですが、コンテキストにバインドされた型には、より高い種類の型パラメーターが必要です(ClassManifestにはありません)。

scala> trait HKTypeClass[CC[_]]
defined trait HKTypeClass

scala> implicit def listHKTC = new HKTypeClass[List] {}
listHKTC: java.lang.Object with HKTypeClass[List]

scala> def frob[CC[_] : HKTypeClass] = implicitly[HKTypeClass[CC]]
frob: [CC[_]](implicit evidence$1: HKTypeClass[CC])HKTypeClass[CC]

scala> frob[List]
res0: HKTypeClass[List] = $anon$1@13e02ed

アップデート

タイプエイリアスを使用して、より種類の多いタイプパラメータを1次コンテキストバインドタイプでバインドできるようにすることができます。型エイリアスを型レベル関数として使用して、1次型からより高種類の型を作成します。ClassManifestの場合、次のようになります。

scala> type HKClassManifest[CC[_]] = ClassManifest[CC[_]]
defined type alias HKClassManifest

scala> def frob[CC[_] : HKClassManifest] = implicitly[HKClassManifest[CC]]         
test: [CC[_]](implicit evidence$1: HKClassManifest[CC])HKClassManifest[CC]

scala> frob[List]                                                       
res1: HKClassManifest[List] = scala.collection.immutable.List[Any]

タイプエイリアスの右側にあるCC[_]は一次タイプであることに注意してください...ここでの下線はワイルドカードです。したがって、ClassManifestの型引数として使用できます。

アップデート

完全を期すために、タイプエイリアスはタイプラムダを使用してインライン化できることに注意する必要があります。

scala> def frob[CC[_] : ({ type λ[X[_]] = ClassManifest[X[_]] })#λ] = implicitly[ClassManifest[CC[_]]]     
frob: [CC[_]](implicit evidence$1: scala.reflect.ClassManifest[CC[_]])scala.reflect.ClassManifest[CC[_]]

scala> frob[List]
res0: scala.reflect.ClassManifest[List[_]] = scala.collection.immutable.List[Any]
于 2011-04-04T17:20:49.757 に答える
5

implicitly[ClassManifest[List[_]]]はの略であることに注意してくださいimplicitly[ClassManifest[List[T] forSome {type T}]]

それが機能する理由ClassManifestです。適切な型引数を期待し、適切な型List[T] forSome {type T}ですListが、型コンストラクターです。(「適切な」などの定義については、Scalaの上位型とは何ですか?を参照してください。)

両方を作成しClassManifest[List[String]]て機能させるには、次のようなさまざまな種類の型パラメーターを受け取るバージョンで何らかの方法でClassManifest[List]オーバーロードする必要があります。ClassManifest

class ClassManifest[T] // proper type
class ClassManifest[T[_]] // type constructor with one type parameter
class ClassManifest[T[_, _]] // type constructor with two type parameters
// ... ad nauseam

(学術的なメモでは、これを行うための「適切な」方法は、種類を抽象化できるようにすることです。

    class ClassManifest[T : K][K]

    implicitly[ClassManifest[String]] // --> compiler infers ClassManifest[String][*]
    implicitly[ClassManifest[List]] // --> compiler infers ClassManifest[List][* -> *]

)。

于 2011-06-22T08:15:15.210 に答える