1

次の例Sの呼び出しから型パラメーターを削除する方法を探しています。apply

object Attribute {
  trait Int    [S] extends Attribute[S]
  trait Boolean[S] extends Attribute[S]  // etc.
}
sealed trait Attribute[S]

trait Attributes[S] {
  protected def get(key: String): Option[Attribute[S]]

  def apply[A <: Attribute[S]](key: String)
                              (implicit tag: reflect.ClassTag[A]): Option[A] = 
    get(key) match {
      case Some(attr: A) => Some(attr)
      case _             => None
    }
}

上記の定義では、テスト ケースは次のようになります。

trait Test[S] {
  def map: Attributes[S]

  map[Attribute.Int[S]]("foo")
}

私がやろうとしているのは、次を許可するように定義を変更するapplyことです:

trait Test2[S] {
  def map: Attributes[S]

  map[Attribute.Int]("foo")   // use partially applied attribute type
}

編集:マリウスの提案とコメントをフォローアップすると、なぜ以下がまだ消去警告を生成するのですか:

import reflect.runtime.universe._

trait Attributes[S] {
  protected def get(key: String): Option[Attribute[S]]

  def apply[A[x] <: Attribute[x]](key: String)
                                 (implicit tag: TypeTag[A[S]]): Option[A[S]] =
    get(key) match {
      case Some(attr: A[S]) => Some(attr)
      case _                => None
    }
}

私には、それは明らかに意味がありません。一方で、利用可能な完全なタイプのタグがA[S]あります。一方、Attributeが不変であるSように、それがなくても完全に機能するはずです。Option[Attribute[S]]Some(attr: A[x])x == S


編集 2 : 解決策の条件は、Attribute型コンストラクターのパラメーターSをメンバー フィールドに移動しないなど、特性の形状が変更されないことです。

4

4 に答える 4

3

unapply暗黙の を活用することを検討しましたClassTagか? ドキュメントを正しく理解していれば、タグの型が完全に一致しないunapply場合、 from は None を返します。attr一致する場合は、タイプの Some を返しA[S]ます。unapply を使用するようにリファクタリングすると、コードは次のようになります。

def apply[A[_] <: Attribute[_]](key: String)
  (implicit tag: reflect.ClassTag[A[S]]): Option[A[S]] =
  get(key) match {
    case Some(attr) => tag.unapply(attr)
    case _             => None
  }
于 2013-05-11T23:11:45.353 に答える
1

一方通行。ネストされた型であっても、任意の型を Int と呼ぶには特定の厚かましさが必要であることに注意してください。

import scala.reflect._

sealed trait Attribute {
  type S
}

object Attribute {
  trait Ints extends Attribute { type S = Int }
}

/** A container for attributes of a certain type.
 */
trait Attributes[E] {
  type Attr = Attribute { type S <: E }
  protected def get(key: String): Option[Attr]

  /** Retrieve the value for the given key.
   *  @tparam A must be our notion of Attribute
   *  @return optionally the A you asked for
   */
  def apply[A <: Attr](key: String)(implicit tag: ClassTag[A]): Option[A] =
    get(key) match {
      case Some(attr: A) => Some(attr)
      case _             => None
    }
}
trait Test2 {
  /** Map keys to ints. */
  def map: Attributes[Int]

  /** Retrieve a value. */
  map[Attribute.Ints]("foo")   // use partially applied attribute type
}
于 2013-05-12T00:22:39.033 に答える
0

これは、@cmbaxter の回答が期待どおりに機能することを示すためのものです。完全に実行できるように、最初のコードも再記述します。

//属性インターフェース

object Attribute {
  trait Int    [S] extends Attribute[S]
  trait Boolean[S] extends Attribute[S]  // etc.
}
sealed trait Attribute[S]

//属性マップ インターフェイス

trait Attributes[S] {
  protected def get(key: String): Option[Attribute[S]]

  def apply[A[_] <: Attribute[_]](key: String)
    (implicit tag: reflect.ClassTag[A[S]]): Option[A[S]] =
    get(key) match {
      case Some(attr) => tag.unapply(attr)
      case _          => None
    }  
  }
}

//テストケース

class Test {
  val map = new Attributes[Foo] {
    def get(key: String) = key match {
      case "foo" => Some(new Attribute.Int    [Foo] { override def toString = "I" })
      case "bar" => Some(new Attribute.Boolean[Foo] { override def toString = "B" })
      case _     => None
    }
  }

  println(s"An int attr named `foo`: ${map[Attribute.Int    ]("foo")}")
  println(s"A bool attr named `foo`: ${map[Attribute.Boolean]("foo")}")
  println(s"An int attr named `bar`: ${map[Attribute.Int    ]("bar")}")
  println(s"A bool attr named `bar`: ${map[Attribute.Boolean]("bar")}")
  println(s"An int attr named `???`: ${map[Attribute.Int    ]("???")}")
  println(s"A bool attr named `???`: ${map[Attribute.Boolean]("???")}")
}

//実行中

new Test

An int attr named `foo`: Some(I)
A bool attr named `foo`: None
An int attr named `bar`: None
A bool attr named `bar`: Some(B)
An int attr named `???`: None
A bool attr named `???`: None
于 2013-05-12T08:25:35.277 に答える