2016-05-27 9 views
7

Biorąc pod uwagę typeclass Printer z zależną typu Show[A]:Jak zakodować tę metodę za pomocą niejawnej grupy parametrów zawierającej typ zależny?

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

Jak mogę kodować tą metodą:

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

Próbowałem dostosować kod do pracy w @ MilesSabin na Gist https://gist.github.com/milessabin/cadd73b7756fe4097ca0 i @ Blog TravisBrown: https://meta.plasm.us/posts/2015/07/11/roll-your-own-scala/, ale nie mogę znaleźć kodowania, które działa.

+0

Czy nie jest to problem braku wielu ukrytych parametrów sekcji w Scala? Sądzę, że Miles Sabin zrobił ostatnio SI, ale nie mogę go znaleźć. (edytuj: widzę, że jest to już wspomniane w tekście, do którego się odnosisz) – Haspemulator

+0

@ Haspemulator Poprawnie. –

+0

Nie oglądałem przykładów. Ale co powiesz na zrobienie nowego typu, który będzie krotkiem 'Printer' i' Show [A] ':' case class Printable [A] (printer: Printer) (niejawny show: printer.Show [A]) '. Następnie spraw, aby 'r' wymagało' Printable [A] '. – ziggystar

Odpowiedz

0

Można wymusić wnioskowanie typu jeden krok na raz, wprowadzając kontekst pośrednich:

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) 
} 
Powiązane problemy