2017-03-13 3 views
0

Ich habe eine List von Artikeln (in diesem Fall Spray Marshallers), die ich im aktuellen Kontext implizit verfügbar machen möchte. Nur zur Klarstellung: Ich will nicht, dass die List selbst implizit verfügbar ist, sondern jedes Element der Liste. Hat jemand einen Trick, um das zu tun? Oder ist das eigentlich nicht möglich, da die genauen implizits zur Kompilierzeit zur Verfügung stehen müssen?Wie stelle ich den Inhalt einer Scala-Liste implizit zur Verfügung?

+0

Haben Sie einen Beispielcode wo/wie Sie es verwenden würden? – Soapy

+1

Für jeden Typ kann nur eine Instanz durch implizite Suche ausgewählt werden. Wenn mehrere Instanzen verfügbar sind und die implizite Suche nicht auswählen kann, erhalten Sie 'error: ambiguous implizite values'. Jedes Element in einer "Liste [T]" hat den Typ "T". Wie würde das funktionieren? –

+0

Etwas mehr Kontext: Ich habe versucht, eine Direktive als Teil einer Bibliothek zu erstellen, die Benutzern erlauben würde, mehrere Versionen ihrer HTTP API zu haben. Diese Richtlinie würde die richtigen Marshaller in den Geltungsbereich bringen. Diese Lösung kombiniert jedoch die Kompilierzeit und die Laufzeitlogik w.r.t. impliziert. Ich habe jetzt einen anderen Pfad gewählt: eine benutzerdefinierte "vollständige" Direktive, die die ursprüngliche ersetzt und eine implizite Liste von Marshallern als Argument verwendet. Diese Direktive wählt den richtigen Marshaller aus und erstellt die Antwort. Klappt wunderbar! Danke für deine Beiträge! –

Antwort

2

In diesem speziellen Fall, wenn ich richtig verstanden habe, müssen Sie alle Ihre spezifischen Marshaller in einem Kontext verfügbar haben, daher müssen Sie jeden von ihnen implizit bereitstellen.

Sie sollten sie in ein Objekt einfügen und sie als implizite Werte definieren.

object Protocol { 
    implicit val marshaller1: ... 
    implicit val marshaller2: ... 
} 

Dann wird durch das Protocol Objekt importieren, würden Sie alle Ihre Einweiser implizit zur Verfügung haben.

Und um Ihre Frage zu beantworten, ja, implicits werden zur Kompilierzeit gelöst. Wenn Sie also einen bestimmten Marshaller verwenden müssen, sucht der Algorithmus für die implizite Auflösung nach einem value des spezifischen Marshaller-Typs. Deshalb können Sie es nicht von einer Liste bekommen, sagen wir, und Sie sollten das auch nicht wollen.

+0

Dies funktioniert nur, wenn die verschiedenen Marshaller als unterschiedliche Typen deklariert sind. Siehe Kommentar oben. Wenn Sie nicht einverstanden sind, geben Sie bitte den funktionierenden Code an. – WillD

+0

Ihre Antwort ließ mich erkennen, dass ich mit meiner Lösung auf der falschen Spur war ... Danke, dass Sie mich zur Besinnung gebracht haben;) –

+0

@ Jan-Pieter Ich bin wirklich froh. –

0

Sie können dies sicherlich erreichen mit unförmigen:

import shapeless._ 
import shapeless.ops.hlist.Selector 

case class A() 
case class B() 
case class C() 

val list : A :: B :: C :: HNil = A() :: B() :: C() :: HNil 

def screamIfAccessible[T](implicit selector: Selector[A :: B :: C :: HNil ,T]) = { 
    selector(list) // Actually picks the T type element 
       // from the HList to work with 
    println("YAY!") 
} 

screamIfAccessible[A] 
screamIfAccessible[B] 

Shapeless - Generic programming with scala

Jede Methode in Ihrem Code, der den Zugriff auf ein Element vom Typ A aus der Liste muss (oder in diesem Fall hList) muss Haben Sie das Selector implizite Argument

Verwandte Themen