3

クラスに抽象型を持つ型の値を与え、後でそのパス依存型を使用したいと思います。次の例を見てください (Scala 2.10.1 を使用):

trait Foo {
  type A
  def makeA: A
  def useA(a: A): Unit
}

object Test {

  class IntFoo extends Foo {
    type A = Int
    def makeA = 1
    def useA(a: Int) = println(a)
  }

  class FooWrap(val a: Foo) {
    def wrapUse(v: a.A) = a.useA(v)
  }

  val foo = new IntFoo

  /* Path dependent locally */
  val bar = foo  
  bar.useA(foo.makeA)   // works

  /* Path dependent through class value */
  val fooWrap = new FooWrap(foo)

  fooWrap.a.useA(foo.makeA)  // fails
  // error: type mismatch; found : Int required: Test.fooWrap.a.A

  fooWrap.wrapUse(foo.makeA) // fails
  // error: type mismatch; found : Int required: Test.fooWrap.a.A

}

まず、ローカルとクラス値のケースの基本的な違い (public の不変値に注意) と、型チェックが失敗する理由 (明らかに ) がわかりませんTest.fooWrap.a.A =:= foo.A。これは Scala コンパイラの制限ですか?

第二に、私がやろうとしていることをどのように達成できますか?

アップデート

これは、ジェネリックとインライン型制約を使用することで実現できるようです。

class FooWrap[T](val a: Foo { type A = T }) {
  def wrapUse(v: T) = a.useA(v)
}

ただし、私の場合、A実際にはより高次の型であるため、例は次のようになります。

trait Foo {
  type A[T]
  def makeA[T]: A[T]
  def useA(a: A[_]): Unit
}

object Test {

  class OptFoo extends Foo {
    type A[T] = Option[T]
    def makeA[T] = None
    def useA(a: A[_]) = println(a.get)
  }

  class FooWrap(val a: Foo) {
    def wrapUse(v: a.A[_]) = a.useA(v)
  }

  val foo = new OptFoo

  /* Path dependent locally (snip) */

  /* Path dependent through class value */
  val fooWrap = new FooWrap(foo)

  fooWrap.a.useA(foo.makeA)  // fails
  // polymorphic expression cannot be instantiated to expected type;
  // found : [T]None.type required: Test.fooWrap.a.A[_]

  fooWrap.wrapUse(foo.makeA) // fails
  // polymorphic expression cannot be instantiated to expected type;
  // found : [T]None.type required: Test.fooWrap.a.A[_]

}
4

2 に答える 2

0

上位の種類の型も、ジェネリック パラメーターとして FooWrap に追加できます。

class FooWrap[T[V]](val a: Foo { type A[V] = T[V] }) {
  def wrapUse(v: T[_]) = a.useA(v)
}

しかし (この例では) 推論は失敗します:

val fooWrap = new FooWrap[Option](foo)

さもないと:

- type mismatch; found : Test.foo.type (with underlying type Test.OptFoo) required: Foo{type A[V] = T[V]}
- inferred kinds of the type arguments (Option[V]) do not conform to the expected kinds of the type parameters (type T) in class FooWrap. Option[V]'s type parameters do not match type T's expected 
 parameters: class Option has one type parameter, but type T has one

他のより良い解決策はありますか?

于 2013-04-23T22:49:42.657 に答える