2016-05-27 32 views
7

Dato un typeclass Printer con un tipo dipendente Show[A]:Come si codifica questo metodo con un gruppo di parametri implicito che contiene un tipo dipendente?

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

Come faccio a codificare questo metodo:

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

Ho cercato di adattare il codice di lavoro in @ MilesSabin di Gist https://gist.github.com/milessabin/cadd73b7756fe4097ca0 e @ Il post del blog di TravisBrown https://meta.plasm.us/posts/2015/07/11/roll-your-own-scala/, ma non riesco a trovare una codifica che funzioni.

+0

non è un problema della mancanza di molteplici parametri sezioni impliciti a Scala? Penso che Miles Sabin abbia fatto un SI con questo recentemente, ma non riesco a trovarlo. (Modifica: Vedo che questo è già menzionato nel senso a cui si fa riferimento) – Haspemulator

+0

@Haspemulator corretto. –

+0

Non ho guardato gli esempi. Ma che ne direste di creare un nuovo tipo che tuplica una 'Stampante' e' Mostra [A] ':' classe del caso Stampabile [A] (stampante: Stampante) (spettacolo implicito: stampante.Mostra [A]) '. Quindi 'r' richiede un' Printable [A] '. – ziggystar

risposta

0

È possibile forzare l'inferenza dei tipi un passo alla volta con l'introduzione di contesti intermedi:

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