2017-01-05 4 views
2

Mit Shapeless habe ich versucht, einen Generic[F] über zu bekommen:Generic [A] wo ist A eine Klasse?

import shapeless._ 

class F(x: Int) 

aber es ist fehlgeschlagen:

scala> Generic[F] 
<console>:20: error: could not find implicit value for parameter gen: shapeless.Generic[F] 
     Generic[F] 
      ^

Kann unförmigen produzieren eine Generic[F]? Wenn das so ist, wie?

+1

Ich bin überrascht über die downvotes. Ich habe diese Frage hauptsächlich gestellt, um die aufschlussreiche Antwort von Travis Brown zu finden. –

+0

Einverstanden-es ist eine vollkommen vernünftige Frage aus meiner Sicht. –

Antwort

6

Welche Darstellung möchten Sie für F? Sie könnten sagen, es sollte HNil sein, aber die x ist nicht sichtbar außerhalb des Körpers der Klasse, so macht Shapeless die Entscheidung, keine Instanz überhaupt bereitzustellen. Dies ist "nur" eine Designentscheidung - aus meiner Sicht die richtige, aber man kann sich leicht vorstellen, dass Shapeless die HNil Instanz für Ihre Klasse liefert.

Es wäre auch relativ einfach sein, eigene Instanz zu definieren, für F, was möglich ist, weil Generic nur eine andere Art Klasse:

import shapeless._ 

class F(x: Int) 

object F { 
    implicit val genericF: Generic.Aux[F, HNil] = new Generic[F] { 
    type Repr = HNil 

    def from(r: HNil): F = new F(0) 
    def to(t: F): HNil = HNil 
    } 
} 

Als eine andere Antwort Notizen, können Sie sich Shapeless eine Instanz zu schaffen Sie, indem Sie Ihre Klasse in eine Fallklasse ändern. Das ist nicht der einzige Weg, wenn auch-Sie auch den Konstruktor Parameter auf einen val ändern könnte oder einfach entfernen:

scala> class F(val x: Int) 
defined class F 

scala> shapeless.Generic[F] 
res0: shapeless.Generic[F]{type Repr = shapeless.::[Int,shapeless.HNil]} = [email protected] 

scala> class F() 
defined class F 

scala> shapeless.Generic[F] 
res1: shapeless.Generic[F]{type Repr = shapeless.HNil} = [email protected] 

Sie könnten nicht der Parameter machen eine var oder die Klasse abstrakt machen, aber (es sei denn, es war versiegelt und Fall Klassen- oder Objektimplementierungen). Oder Sie könnten das, aber dann müssten Sie Ihre eigenen Instanzen erneut definieren, und Sie würden den Vertrag in der Generic Dokumentation brechen, die besagt, dass der charakterisierte Typ ein "unveränderlicher Datentyp sein sollte, der einen kanonischen Weg hat Instanzen erstellen und dekonstruieren ".

Soweit ich weiß, die genauen Details, welche Arten von Vereinbarungen der Klassendefinitionen Generic Instanzen wird nirgendwo dokumentiert (und the source ist nicht leicht zu lesen), aber es ist ziemlich einfach, die Grenzen zu testen, die Sie sind daran interessiert, bestimmte Fälle in der REPL auszuprobieren.

Verwandte Themen