0

Listableがケース クラスのコンパニオン オブジェクトに混在することを意図しているこの例を考えてみましょう。したがって、 を呼び出すには、 が定義されたを拡張Writer.gridするコンパニオン オブジェクトが必要です。(たとえば、任意のリストをCSV 形式に変換するとします。)AListable[A]implicit Writer[A]Listable

trait Listable[A] {
    def list: List[A]
}

object Writer {
    def grid[A <: Listable[A]](listable: A)(implicit w: Writer[A]): String = {  
        listable.list.map(w.write(_).mkString(",")).mkString("\n")
    }
}

trait Writer[A] {
    def write(a: A): List[String]
}

そして、ここに素朴な実装があります:

case class Test(id: Int, text: String)

object Test extends Listable[Test] {
    def list = List(Test(1, "test"))

    implicit val wrt = new Writer[Test] {
        def write(t: Test) = List(t.id.toString, t.text)
    }
}

これはコンパイルされますが、listable: A実際にはオブジェクトTestを参照し、ケースではクラスを参照しているAため、機能しません。w: Writer[A]TestWriter.grid(Test)

の署名を捨てListableて要求することで、この問題をある程度回避できます。implicit List[A]grid

def grid[A](implicit w: Writer[A], list: List[A]): String = ...

しかし、私は次のことを好みます:

  1. 予期しない結果を生成する可能性があるような暗黙的な関数は必要ありません。
  2. list他の場所でも使用されるため、wrap に特別なタイプを使用しないでください。
  3. gridメソッドの定義を の外部に保持しますListable

これを機能させるために の署名を作り直すことは可能Writer.gridですか? (またはその他の構造変更)

4

2 に答える 2

1

基本的に、Engene は実用的な解決策を指摘しました。私が言いたいのは、あなたの状況で本当に奇妙なのはlistable、グリッド関数にインスタンスが必要ないということです。この事実は元のコードからは明らかではありませんが、Eugene のコードからわかるように、引数はまったく使用されていません。

したがって、あなたがやろうとしていることは、コンパニオン オブジェクトに特別な目的のために特別なインスタンスのインスタンスを持たせることだと思います。おそらく私は間違っています。しかし、その名前Listable[A]は本当に紛らわしいです。コンパニオン オブジェクトの特性を説明しようとしている場合は、 sth のようListableMeta[A]に名前を付けることができます。これはより理にかなっています。

trait ListableMeta[A] {
    def list: List[A]
}

object Writer {
    def grid[A : ListableMeta](implicit w: Writer[A]): String = {
        implicitly[ListableMeta[A]].list.map(w.write(_).mkString(",")).mkString("\n")
    }
}

trait Writer[A] {
    def write(a: A): List[String]
}

case class Test(id: Int, text: String)

trait InImplicit {
    implicit val injectThisToImplicits: this.type = this
}

object Test extends ListableMeta[Test] with Writer[Test] with InImplicit {
    def list = List(Test(1, "test"))

    def write(t: Test) = List(t.id.toString, t.text)
}

あなたがする必要があるのは、基本的Writer.grid[Test]に具体的なインスタンスを渡すのではなく、これでうまくいくはずです。しかし、ここでの明確なポイントは、すべてのものに型クラスを使用することです。型クラスと型境界を組み合わせて使用​​すると、混乱が生じる可能性があります。

于 2014-11-13T03:02:34.823 に答える