13

私は楽しみのために Scala 2.8 をいじり、型コンストラクターに「as」メソッドを追加して、あるファンクターから別のファンクターに変換できるpimpを定義しようとしていました (ここで必ずしもファンクターを扱っているわけではないという事実を見落としてください)。 . たとえば、次のように使用できます。

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
    }
}

ただし、 の定義には、 「パラメータ化された型 G[T] を実存的に抽象化できません」naturalTransformationsというエラーが表示されます。これを修正するには、次のように追加のクラスとともに書き直すことができます。naturalTransformationsTransformable

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)

そしてそれはうまくいくようです。しかし、私の最初の試みは同等だったはずなので、なぜ失敗したのか、エラーメッセージが何を意味するのか興味があります.

4

2 に答える 2

11

私の推測では、これは、仕様 § 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}

于 2010-06-26T04:33:04.870 に答える
0

私には、これは一般的なケースに対する単純さのように聞こえます。既存の型でインスタンス化された型コンストラクターをキャプチャするブロックが作成されるたびに新しい型変数が生成される可能性がありますが、それはエラー診断を理解するのをより難しくします。

また、クラスがあると、リフレクションによってas()メソッドを呼び出すのではなく、呼び出しが高速のINVOKEVIRTUALに変わることに注意してください。

于 2010-06-26T11:06:24.737 に答える