「パラメーター化されたタイプを実存的に抽象化することはできません…」
質問
私は楽しみのためにScala 2.8をいじり、定義しようとしていました ポン引き これにより、コンストラクターを入力する「as」メソッドが追加され、あるファンチャーから別のファンチャーに変換できます(ここでは必ずしもファンクターを扱っているわけではないという事実を見落としてください)。たとえば、次のように使用できます。
val array:Array[T]
val list:List[T] = array.as[List]
だから私がやろうとしたことは次のとおりです。
object Test {
abstract class NatTrans[F[_], G[_]] {
def convert[T](f:F[T]):G[T]
}
implicit def array2List:NatTrans[Array, List] = new NatTrans[Array, List] {
def convert[T](a:Array[T]) = a.toList
}
// this next part gets flagged with an error
implicit def naturalTransformations[T, F[_]](f:F[T]) = new {
def as[G[_]](implicit n:NatTrans[F, G]) = n convert f
}
}
ただし、の定義 naturalTransformations
エラーがフラグが付けられています 「パラメーター化されたタイプG [T]を介して実存的に抽象化することはできません」. 。これを修正するために、書き直すことができます naturalTransformations
追加のクラスとともに Transformable
そのようです:
class Transformable[T, F[_]](f:F[T]) {
def as[G[_]](implicit n:NatTrans[F, G]) = n convert f
}
implicit def naturalTransformations[T, F[_]](f:F[T]) = new Transformable[T, F](f)
そして、それはうまくいくようです。しかし、私の最初の試みは同等だったはずだったので、なぜそれが失敗したのか、エラーメッセージが何を意味するのか興味があります。
解決
私の予想は、これが仕様の次のステートメントのために、§6.11がブロックされているからだということです。
局所的に定義されたタイプ定義タイプt = tは、実存句タイプt>:t <:tに拘束されます。 Tがタイプパラメーターを運ぶ場合、これはエラーです。
そして、構造的インスタンス作成式がブロックに評価されるため、
new {def greet{println("hello")}}
の速記です
{ class anon$X extends AnyRef{ def greet = println("hello") }; new anon$X }
したがって、前述の制限により、ブロック式(仕様の§6.10に従って)を評価します。この制限がある理由はわかりません。スローされているエラーは、Typersクラスで見つけることができます この場所, 、これは、この制限があなたが見るエラーの原因であることを確認しているようです。あなたが述べたように、クラスの関数をエンコードすると、ブロック式の制限が削除されます。
scala> class N[M[_]]
defined class N
scala> class Q { def as[M[_]](n:N[M]) = null}
defined class Q
scala> new { def as[M[_]](n:N[M]) = null}
:7: error: can't existentially abstract over parameterized type M
new { def as[M[_]](n:N[M]) = null}
他のヒント
私にとって、これは一般性のケースに対するシンプルさのように聞こえます。ブロックが作成されるたびに生成される新しいタイプ変数がある可能性がありますが、実存的なタイプでインスタンス化されたタイプコンストラクターをキャプチャしますが、エラー診断がより困難になるでしょう。
また、クラスを持つことは呼び出しを呼び出すのではなく、速いInvokeVirtualに変えることに注意してください なので() 反射による方法。