2011-01-28 24 views
2

私はデータ構造を実装しており、適切なキータイプをラップする限り、どのタイプもキーとして使用できるようにしたいと考えています。私はこのキータイプの特性を持っています。この考え方は、基底型から基底型への暗黙的な変換を行うことで、もう1つの方法は基本型を(事実上)使用することです。特徴は次のようになります。一般的な形質の暗黙的な変換

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]?コンパニオンオブジェクトは、悲しいことに抽象メソッドを持つことはできません。

これがうまくいくとすれば、企業全体が実現可能であるとか、あるいは明示されたユースケースが複数の連鎖暗黙変換を必要とするのでしょうか? (私が読んだとして連鎖は、発生しません。)

補遺:上記の定義では、私はsortWith(_.key <= _.key)を使用しますが、sortBy(_.key)を使用しないことにより、(K <% Key[K]下)Node(key : K, ...)の順序を並べ替えることができます。だから明らかに、KからKey[K]への変換は暗黙のうちにどこからでも宣言されていますが、OrderingKey[K]に暗黙的にはありません。ここで何が起こっているのですか?ここで

+0

なぜ、注文ではなくオーダーを使用しますか? – Landei

+0

タイプ*は*オーダーされていますが、*オーダーメントがあるためです。違いはありますか? Orderingを生成する汎用/抽象関数を実装するにはどうすればよいですか? – Raphael

+0

私はおそらく 'foo'の暗黙的なパラメータがうまくいくので順序を渡すと思っていましたが、もちろんこれはビューバインドと競合します。 – Raphael

答えて

0

をしない、私は参考のために、現在最高のバージョンを保持します。より焦点を絞った質問にthis answerを使用する。 this oneに従って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]インタフェース使用してこのコードを仮定:map直接Seq[Key[K]]をもたらすので、これはコンパイルすること

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

に注意。並べ替えに必要な変換はありません。

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への変換が見つかりません:私たちは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) 
} 

を言う

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

これは変です。 であり、汎用型パラメータで宣言されている場合はKey[String]からStringに変換されます。

0

はあなたの問題を解決(希望は私が正しくあなたの要件を理解する)ことも可能である。この場合Key[T]

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

タイプTKeyable[T]のためのラッパーがKey[T]にタイプTに変換することができますタイプのcalssです。私はまたbase2keyのように見える方法を示した。

+0

これはうまくいくかもしれませんが、試行しませんでしたが、可能なキータイプの数が制限されています(つまり、基本タイプはKeyableまたはコンバージョンを実装していません)。もっと暗黙的な文字列を引くことができるかもしれませんが、それは私が既に持っているものよりも複雑になります。 – Raphael

+0

@Raphael:基本型のすべての暗黙の 'Keyable'値を' Object Keyable'に置くことができ、それらは常に利用可能です。 – tenshi

+0

男の子、それはハックだ。私はScalaにとってもっと愚かな解決策を探しています。とにかく、あなたの邪魔に感謝します。 – Raphael

1

あなたは「Key[T]の拡張型は暗黙の変換T => Key[T]が付いてくることを静的に宣言することはできますか?コンパニオンオブジェクトは抽象メソッドを持つことができません。

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

補足について:あなたが「KからKey[K]への変換は、私がどこでも宣言されていなくても暗黙的に起こる」と驚いていると言います。事は、あなたがそれを宣言しました、次のとおりです。T <% Key[T](私はここではなく、KTを使用しています、あなたがベースの概念を混同しているようだ* T * YPEと*ここK * EY?)。これにより、あなたがsortWith(_ <= _)を行うときに(<=が特色Ordered[Key[T]]ごとに定義されている)Key[T]Tを強制

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

と同じです。

あなたのノードを例にとり、なぜこの答えに役立ちます

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

希望...

+0

1)はい、私は 'K <%Key [K]'をアサートしますが、実際にこの変換を実装したことはありません。私は実装( 'StringKey')が暗黙的にそのコンストラクタによってこれを提供していると仮定します。 2)私は 'T'と' Key'を一貫して使用しましたが、ここでは分かりません。 'Key'の文脈で' T'を使用するのは、それが型だけであったのですが、 'K'はキー型であればその使用のコンテキストで使用します。わかりやすくするためにこれを編集します。 3)あなたの提案については、これは注文を上げる責任を移しています。そうですか?具体的なタイプが利用可能でなければならないので、実際にはうまくいくかもしれません。ありがとう! – Raphael

+0

なぜ私はすでにキーが 'Ordered 'であることが分かっているので、なぜこれが必要なのか不思議です。奇妙な。 – Raphael

+0

あなたのソリューションは、私が大いに採用している 'test'の' K 'から 'Key [K]'への暗黙的な変換を失います。両方を組み合わせることはできますか? – Raphael

関連する問題