2016-05-27 17 views
7

ein typeclass Printer mit einem abhängigen Typ Gegeben Show[A]:Wie kodiere ich diese Methode mit einer impliziten Parametergruppe, die einen abhängigen Typ enthält?

trait Printer { 
    type Show[A] 
    def show[A](x: A)(implicit z: Show[A]): String 
} 

object Printer { 
    // the intent here is this is the dumb fallback 
    // and a user can have a better alternative in scope 
    implicit val dumbPrinter: Printer = new Printer { 
    type Show[A] = DummyImplicit 
    def show[A](x: A)(implicit z: DummyImplicit): String = x.toString 
    } 
} 

Wie kodieren ich diese Methode:

def r[A](x: A)(implicit printer: Printer, show: printer.Show[A]): String = 
    printer.show(x)(show) 

Ich habe versucht, den Arbeitscode in @ MilesSabin den Kern https://gist.github.com/milessabin/cadd73b7756fe4097ca0 und anzupassen @ TravisBrowns Blogpost https://meta.plasm.us/posts/2015/07/11/roll-your-own-scala/, aber ich kann keine Kodierung finden, die funktioniert.

+0

Ist es nicht ein Problem des Mangels an mehreren impliziten Parameter Abschnitte in Scala? Ich denke, Miles Sabin hat kürzlich eine SI gemacht, aber ich kann es nicht finden. (edit: Ich sehe, dass dies bereits in dem Text erwähnt wird, auf den Sie sich beziehen) – Haspemulator

+0

@Haspemulator Korrekt. –

+0

Ich habe mir die Beispiele nicht angesehen. Aber wie wäre es mit einem neuen Typ, der ein 'Printer' und' Show [A] ':' case klasse Printable [A] (Drucker: Drucker) tupft (implizite show: printer.Show [A]) '. Dann mache "r" ein "Printable [A]". – ziggystar

Antwort

0

Sie können durch die Einführung von Zwischen Kontexten zu einem Zeitpunkt Typinferenz einen Schritt erzwingen:

object example { 

    trait AnyPrinter { 
    type Show <: AnyShow 
    } 

    trait AnyShow { 
    type X 
    def apply(x: X): String 
    } 

    def print[P <: AnyPrinter](implicit p: P): print[P] = new print[P] 

    class print[P <: AnyPrinter] { 
    def it[E](e: E)(implicit s: P#Show { type X = E }): String = s(e) 
    } 

    // the intent here is this is the dumb fallback 
    // and a user can have a better alternative in scope 
    implicit object DumbPrinter extends AnyPrinter { 
    type Show = AnyDumbShow 
    } 
    trait AnyDumbShow extends AnyShow { 
    def apply(x: X): String = x.toString 
    } 
    case class DumbShow[Z]() extends AnyDumbShow { type X = Z } 
    implicit def dumbShow[Z]:DumbShow[Z] = DumbShow() 

    val buh: String = print.it(2) 
}