2016-11-23 17 views
1

から暗黙のインポート:ユーザー缶は、任意の型Tのための拡張ライブラリとして実装された文字列に型Tの値を変換するので、ここで特性は、すべての型クラスです実装する必要があります。は私がScalaでは型クラスのビット洗練された例を実装しようとしているサブクラス

trait Printable[T] { 
    def asString(value: T): String 
} 

私たちが仕事をするためにコールするつもりだ機能:いくつかのデフォルトの種類の型クラスのシリーズと

object Printer { 
    def print[T](value: T)(implicit p:Printable[T]): String = p.asString(value) 
} 

オブジェクト(だけint型&長くここに例):

object SimpleFormats extends Formats 

trait Formats { 
    implicit val intFormat = new Printable[Int] { 
    override def asString(value: Int) = value.toString 
    } 
    implicit val longFormat = new Printable[Long] { 
    override def asString(value: Long) = value.toString 
    } 
} 

フロートとダブルのような他のタイプのライブラリを拡張したいとします。そこで彼は別のオブジェクトを作成し、最初のオブジェクトをサブクラス化します。

object ExtendedFormats extends Formats { 
    implicit val floatFormat = new Printable[Float] { 
    override def asString(value: Float) = value.toString 
    } 
    implicit val doubleFormat = new Printable[Double] { 
    override def asString(value: Double) = value.toString 
    } 
} 

そして、我々のライブラリを使用して最終的には、メインのアプリ:ここでのアイデアは、型クラスのデフォルトのコレクションは、ユーザーが提供するタイプの任意の数のために拡張することができるように、ベースオブジェクトに新しい暗黙のメンバーを追加することです。それはPrinter[T]単一の特定の暗黙的に供給することはできませんので、異なる種類の操作を行う2例の機能として、があります。

  • 複数の操作はPrinterが供給されることができる種類の事前に把握していない
  • 複数の種類にありますユーザーによって。

だから、メインのアプリは、次のようになります。

object Example { 
    // compiles OK, uses only default typeclasses 
    def simpleExample(implicit formats: Formats) = { 
    import formats._ 
    Printer.print(42) + Printer.print(24L) 
    } 

    // compilation failed, cannot find Printable[Float] 
    // uses user-supplied formats 
    def extendedExample(implicit formats: Formats) = { 
    import formats._ 
    Printer.print(42f) + Printer.print(31337.0) 
    } 

    def main(args: Array[String]): Unit = { 
    implicit val formats = ExtendedFormats 
    println(simpleExample) 
    println(extendedExample) 
    } 
} 

私はScalaのコンパイラは、それが実際にExtendedFormatsであるという事実を無視して、Formatsから暗黙をインポートしようとしていることがわかります。

質問:

  • 例で説明したように、サブクラスから暗黙にインポートする方法はありますか?
  • ユーザ供給型クラスのバッチのためのよりよい解決策はありますか?
+0

typullassesについては、[simulacrum](https://github.com/mpilquist/simulacrum)をご覧ください。 –

答えて

2

あなたはあなたのコードがFloatためとDoubleためPrintableが必要であることが事前にわかっているなら、あなたはそれを直接宣言することがあります

def extendedExample(implicit floatPrintable: Printable[Float], doublePrintable: Printable[Double]) = { 
    Printer.print(42f) + Printer.print(31337.0) 
} 

それともFormat様形質のコレクションを作成:

trait FormatDouble { 
    implicit val doubleFormat: Printable[Double] 
} 
をその後、

、あなたが必要なのですかどのような種類を指定するためにそれを使用します。

def extendedExample(implicit formats: Formats with FormatDouble with FormatFloat) = { 
    import formats._ 
    Printer.print(42f) + Printer.print(31337.0) 
}