私は高次の型を持っており、それを使っていくつかの DSL を構築しようとしています。そして、この型を明示的に指定せずに型を受け入れることができる関数を定義する方法を探しています。
自己記述的な例:
class Wrap[T] (val data : T)
class DSL {
def doSomething[T](x : Wrap[T]) =
println(x.data)
def <<=[T,W <: Wrap[T]](arg : W) : W = {
doSomething(arg)
arg
}
def <<-[T](arg : Wrap[T]) : Wrap[T] = {
doSomething(arg)
arg
}
def <<+[W <: Wrap[_]](arg : W) = {
doSomething(arg)
arg
}
def <<~(arg : Wrap[_]) = {
doSomething(arg)
arg
}
}
class ExtendedInt(x : Int) extends Wrap[Int](x) {
def expose() = println(data)
}
object Test {
val dsl = new DSL
val exi = new ExtendedInt(3)
val x1 = dsl <<= exi
val x2 = dsl <<- exi
val x3 = dsl <<+ exi
val x4 = dsl <<~ exi
x1.expose()
x2.expose()
x3.expose()
x4.expose()
}
4 つの異なる方法を試しましたが、4 つの異なるエラーが発生しました。
Casting.scala:15: error: no type parameters for method doSomething: (x: Wrap[T])Unit exist so that it can be applied to arguments (W)
--- because ---
argument expression's type is not compatible with formal parameter type;
found : W
required: Wrap[?T]
doSomething(arg)
^
Casting.scala:32: error: inferred type arguments [Nothing,ExtendedInt] do not conform to method <<='s type parameter bounds [T,W <: Wrap[T]]
val x1 = dsl <<= exi
^
Casting.scala:38: error: value expose is not a member of Wrap[Int]
x2.expose()
^
Casting.scala:40: error: value expose is not a member of Wrap[_$2]
x4.expose()
^
four errors found
すべてのエラーは非常に説明的です。私は、scala のぎこちない型システムと制限に反対しません。しかし、私はまだ目的から遠く離れており、望ましい機能を実装するための別のハックを探すことに前向きです。
私が見落としている他の方法はありますか?