2017-01-30 7 views
0

Gegeben:Definition `implizit def 'w/Implizit?

trait Foo[A] 
class B 

und die folgende implicit def dann:

implicit def f[A](b: B)(implicit ev: Foo[A]): String = "foo" 

ich versuchte B => String implizit zu lösen, aber es versäumt zu kompilieren:

Erraten
scala> implicitly[B => String] 
<console>:15: error: No implicit view available from B => String. 
     implicitly[B => String] 
       ^

ich, dass die implicit Foo[A] wirft sozusagen einen Schraubenschlüssel in meine implizite Auflösung von B => String.

Wie kann ich die implicitly 's Argument, i..e B => String, so dass die oben genannten kompiliert?

+1

Haben Sie zuvor 'implizit [Foo [B]]' versucht (was ist die Voraussetzung für Ihre implizite Konvertierung)? – cchantep

+0

Das ist ein guter Punkt - mein Fehler. –

+1

Übrigens ist ein "implizites A => B" eine "implizite Umwandlung" und nicht eine Typenklasse, die zu der entsprechenden Warnung führt (da sie den Code schnell überladen kann). Würde lieber ein 'Merkmal verwenden MyFunT [A] erweitert (A => String)'. – cchantep

Antwort

1

ähnlicher Code typeclass anstatt implizite Konvertierung:

trait MyFunT[A] extends (A => String) 

object MyFunT { 
    /**Factory to easily define an instance from a fun */ 
    def apply[A](f: A => String): MyFunT[A] = new MyFunT[A] { 
    def apply(a: A): String = f(a) 
    } 
} 

implicit def foo[A](implicit ev: Foo[A]) = MyFunT[A] { a: A => /* do something with `a` and `ev` */ "foo" } 

Auch wenn implicit s Basis/erfordern andere implicit üblich ist, würde ich darauf zu achten, rate nicht „zu langer Kette“ darüber zu haben, .

+0

Denkst du, dass das Hinzufügen der folgenden Funktion zu 'Objekt Foo' auch eine gute Wahl wäre:' def Instanz [A] (f: A => Foo [A]): ​​Foo [A] '? Ich habe diese Frage gestellt, nachdem ich den [Shapeless Guide] erneut gelesen habe (https://github.com/undscoreio/shapeless-guide), wo die Typklasse 'CsvEncoder' erwähnt wird: https://github.com/kevinmeredith/shapeless_book_exercises/ Blob/Master/Src/Haupt/Scala/Net/CsvEncoder.scala # L12-L15. –

+1

Eine solche Factory-Funktion heißt aften "apply" wie im Beispiel – cchantep

+0

Nach dem Lesen Ihrer hilfreichen Antwort und Kommentare ist es mir nicht klar, warum es sinnvoll ist, 'MyFunT' zu erweitern (A => String)'. Was, wenn überhaupt, wäre verloren, wenn Sie diese Vererbung entfernen würden? –