2

私はデータ構造を実装しており、ユーザーがそれをラップする適切なキータイプを提供する限り、キーとして任意のタイプを使用できるようにしたいと考えています。このキータイプには特徴があります。アイデアは、ベースからキータイプへの暗黙の変換を行い、逆に(事実上)ベースタイプのみを使用することです。特性は次のようになります。

trait Key[T] extends Ordered[Key[T]] {
  def toBase : T

  // Further stuff needed for datastructure...
}
object Key {
  implicit def key2base[T](k : Key[T]) : T = k.toBase
}

コールサイトコードは次のようになります。

def foo[K <% Key[K]]( bar : Seq[K] ) = bar.sorted(0)

計画では、タイプの値は、順序付けされたものKに暗黙的に変換されるKey[K]か、順序付けが暗黙的にKey[K]使用される必要があるため、すべてがうまくいくはずです。もちろん、base2key特性自体に暗黙的に実装する方法はありません。または、暗黙的に渡されたクラスマニフェストを使用している可能性がありますか?これを考慮した参考文献は見つかりませんでした。

Key[T]拡張する型には暗黙の変換が伴うことをどういうわけか静的に主張することは可能T => Key[T]ですか?悲しいことに、コンパニオンオブジェクトは抽象的なメソッドを持つことができません。

これがうまくいくと仮定すると、企業全体が実現可能ですか、それとも、述べられているユースケースには複数の連鎖された暗黙の変換が必要ですか?(私が読んだように、Chainingは起こりません。)

補遺:上記の定義では、を使用してNode(key : K, ...)(下のK <% Key[K])シーケンスを並べ替えることができますが、を使用することはできsortWith(_.key <= _.key)ませんsortBy(_.key)。したがって、明らかに、からKへの変換Key[K]は、私がどこにも宣言したことがない場合でも、暗黙的に発生Orderingしますが、暗黙的に使用できるものはありませんKey[K]。ここで何が起こっているのですか?

4

3 に答える 3

1

Key[T]「悲しいことに、拡張する型には暗黙の変換が伴うことを静的に主張することは可能T => Key[T]ですか?コンパニオンオブジェクトは抽象メソッドを持つことができません。」

Tただし、例は静的アサーションです。からのビューが必要な場合はKey[T]、コンパイル時に、fooキーに持ち上げることができる型のみを呼び出すことができるとアサーションします。それとも私は何かを誤解していますか?

補遺に関して:あなたは、「私がどこにも宣言していなくても、からKへの変換Key[K]が暗黙的に行われる」ことに驚いていると言います。つまり、あなたはそれを宣言しました:(T <% Key[T]私はT代わりにここを使用していKます、あなたはここでベース* T *ypeと* K * eyの概念を混同しているようです?)これはと同じです

def foo[T](bar : Seq[T])(implicit view: T => Key[T]) = bar.sortWith(_ <= _)(0)

したがって、あなたsortWith(_ <= _)が強制TするときKey[T](これ<=は特性ごとに定義されますOrdered[Key[T]])。

Nodeの例を見て、やってみませんか

case class Node[K](key: K)
def test[K](bar: Seq[Node[K]])(implicit ord: Ordering[K]) = bar.sortBy(_.key)(0)

それが役立つことを願っています...

于 2011-01-28T21:06:34.737 に答える
0

これがあなたの問題に対する可能な解決策です(私があなたの要件を正しく理解したことを願っています):

// Key stuff

trait Keyable[T] {
  def toKey(t: T): Key[T]
}

trait Key[T] extends Ordered[Key[T]] {
  def toBase() : T
}

object Key {
  implicit def key2base[T](k : Key[T]) : T = k.toBase
  implicit def base2key[T : Keyable](k : T) : Key[T] = implicitly[Keyable[T]].toKey(k)
}

// more concrete stuff - namely A

class A(val i: Int) {
  override def toString = "A {" + i + "}"
}

object A {
  implicit val aKeyable = new Keyable[A] {
    def toKey(t: A) = new Key[A] {
      def toBase() = t
      def compare(that: Key[A]) = t.i compare that.i
    }
  }
}

// testing

def foo[K : Keyable](bar: Seq[K]) = bar.sortBy(implicitly[Keyable[K]].toKey)

val list = List(new A(5), new A(1), new A(3))

println(foo(list)) // prints: List(A {1}, A {3}, A {5})

この場合Key[T]はtypeのラッパーであり、typeTをにKeyable[T]変換できるtypecalssです。また、どのように見えるかを示しました。TKey[T]base2key

于 2011-01-28T20:25:13.587 に答える
0

この回答では、参照用に現在最適なバージョンを保持します。この回答をより焦点を絞った質問に使用します。これによると2.9で廃止されます。

Key特性は変更されません。説明のために特定の関数を追加します。

trait Key[T] extends Ordered[Key[T]] {
  def toBase : T
  def foo(i : Int) : Key[T]
}
object Key {
  implicit def key2base[T](k : Key[T]) : T = k.toBase
  implicit def ordering[T <% Key[T]] = new Ordering[T]{
    def compare(x: T, y: T) = x compare y
  }
}

以下は期待どおりに機能します(実行さimport Key._れた場合)。

def min[K <% Key[K]](l : Seq[K]) : K = l.sorted.head

単純ながありclass Node[K](val key : K)ます。繰り返しますが、物事は期待どおりに機能します。

def min[K <% Key[K]](l : Seq[Node[K]]) : Node[K] = l.sortBy(_.key).head

Key[T]別の例として、インターフェースのみを使用するこのコードを想定します。

def test[K <% Key[K]](bar : Seq[K]) = 
  bar.map(_.foo(3)).sorted

が直接mapを生成するため、これはコンパイルされることに注意してください。Seq[Key[K]]並べ替えに変換は必要ありません。さて、適切な実装があればKey

class StringKey(val key : String) extends Key[String] {
  def foo(i : Int) =  StringKey(this.key + "_" + i)
  def toBase = key
  override def compare(other : Key[String]) = -1*this.key.compare(other.toBase)
}
object StringKey {
  def apply(key : String) = new StringKey(key)
  def unapply(key : String) = Some(key)
  implicit def string2key(s : String) = StringKey(s)
}

以下が機能するはずです。

import StringKey.string2key
import Key.key2base
val bla : Seq[String] = test(Seq("b", "c", "a")).map(_.capitalize)
println(bla)
// expected output: Seq(C_3, B_3, A_3)

しかし実際には、からStringKeyへの変換Stringは見つかりません。

error: value capitalize is not a member of this.Key[java.lang.String]

これは奇妙です; ジェネリック型パラメーターで宣言されている場合は、からKey[String]への変換があります。String

于 2011-01-31T17:43:33.800 に答える