2

無関係なタイプ A、B、C を格納するために、異種のタイプセーフ コンテナが必要です。

これは一種のタイプレベル仕様です:

trait Container {
  putA(a: A) 
  putB(b: B)
  putC(c: C)
  put(o: Any) = { o match {
    case a: A => putA(a)
    case b: B => putB(b)
    case c: C => putC(c)
  }
  getAllAs : Seq[A]
  getAllBs : Seq[B]
  getAllCs : Seq[C]
}

このコンテナをサポートするのに最適なタイプはどれですか?

タイプ A、B、C の Containerable[T] タイプクラスを作成する価値はありますか?

ありがとう。

4

4 に答える 4

7

他の人が示唆しているように、形のないタイプを活用できますCoproduct。これが例です。

// let's define a Coproduct of the two types you want to support
type IS = Int :+: String :+: CNil

// now let's have a few instances
val i = Coproduct[IS](42)
val i2 = Coproduct[IS](43)
val s = Coproduct[IS]("foo")
val s2 = Coproduct[IS]("bar")

// let's put them in a container
val cont = List(i, s, i2, s2)

// now, do you want all the ints?
val ints = cont.map(_.select[Int]).flatten

// or all the strings?
val strings = cont.map(_.select[String]).flatten

// and of course you can add elements (it's a List)
val cont2 = Coproduct[IS](12) :: cont
val cont3 = Coproduct[IS]("baz") :: cont2

もちろん、これは一般的なコンテナーの最も直感的な API ではありませんがCoproduct、複数の型を表すために を使用してカスタム クラス内のロジックを簡単にカプセル化できます。

ここに実装のスケッチがあります

import shapeless._; import ops.coproduct._

class Container[T <: Coproduct] private (underlying: List[T]) {
  def ::[A](a: A)(implicit ev: Inject[T, A]) =
    new Container(Coproduct[T](a) :: underlying)

  def get[A](implicit ev: Selector[T, A]) =
    underlying.map(_.select[A]).flatten

  override def toString = underlying.toString
}

object Container {
  def empty[T <: Coproduct] = new Container(List[T]())
}

scala> type IS = Int :+: String :+: CNil
defined type alias IS

scala> val cont = 42 :: "foo" :: "bar" :: 43 :: Container.empty[IS]
cont: Container[IS] = List(42, foo, bar, 43)

scala> cont.get[Int]
res0: List[Int] = List(42, 43)

scala> cont.get[String]
res1: List[String] = List(foo, bar)
于 2014-10-26T14:27:19.713 に答える
2

Miles Sabin はボックス化されていない共用体型に関する投稿を書きました。これは、彼のshapelessライブラリのCoProductとして実装されています。

shapeless にはCoproductタイプがあり、ScalaEitherを任意の数の選択肢に一般化したものです。

私は間違いなく shapeless の専門家ではありませんが、新しい質問を作成するか、shapeless タグを使用して質問を編集すると、使用に必要な支援を受けることができますCoProduct

于 2014-10-25T20:37:30.877 に答える