2017-02-02 2 views
2

La commande d'implicite semble importer lors de l'utilisation de shapeless. Regardez l'exemple de code ci-dessous où cela ne fonctionnera pas.Ordonnancement de la méthode implicite et mappage avec shapeless

import shapeless._ 

case class Userz(i: Int, j: String, k: Option[Boolean]) 

object r { 
    def func(): Userz = { 
    val a = Userz(100, "UserA", Some(false)) 
    val b = Userz(400, "UserB", None) 

    val genA = Generic[Userz].to(a) 
    val genB = Generic[Userz].to(b) 

    val genC = genA zip genB 

    val genD = genC.map(Mergerz) 
    val User = Generic[Userz].from(genD) 
    return User 
    } 
} 
object Mergerz extends Poly1 { 
    implicit def caseInt = at[(Int, Int)] {a => a._1 + a._2} 
    implicit def caseString = at[(String, String)] {a => a._1 + a._2} 
    implicit def caseBoolean = at[(Option[Boolean], Option[Boolean])] {a => Some(a._1.getOrElse(a._2.getOrElse(false)))} 
} 

r.func() 

Et le code ci-dessous qui fonctionnera

import shapeless._ 

case class Userz(i: Int, j: String, k: Option[Boolean]) 

object Mergerz extends Poly1 { 
    implicit def caseInt = at[(Int, Int)] {a => a._1 + a._2} 
    implicit def caseString = at[(String, String)] {a => a._1 + a._2} 
    implicit def caseBoolean = at[(Option[Boolean], Option[Boolean])] {a => Some(a._1.getOrElse(a._2.getOrElse(false)))} 
} 

object r { 
    def func(): Userz = { 
    val a = Userz(100, "UserA", Some(false)) 
    val b = Userz(400, "UserB", None) 

    val genA = Generic[Userz].to(a) 
    val genB = Generic[Userz].to(b) 

    val genC = genA zip genB 

    val genD = genC.map(Mergerz) 
    val User = Generic[Userz].from(genD) 
    return User 
    } 
} 


r.func() 

Ma question est, pourquoi les questions d'ordre? J'ai déjà essayé d'importer les implicits qui ne fonctionnent pas.

Répondre

1

Parce que l'inférence de type dans un fichier fonctionne essentiellement de haut en bas. Quand il est typechecking func, il n'a pas obtenu à caseInt etc. et ne sait pas qu'ils conviennent. Annoter leurs types devrait fonctionner aussi, et est généralement recommandé pour implicits, mais il peut être problématique lors de l'utilisation d'une bibliothèque comme Shapeless: voir Shapeless not finding implicits in test, but can in REPL pour un exemple.

+1

Je recommande toujours d'annoter les définitions implicites lorsque je travaille avec Shapeless. Il y a des situations assez rares où cela peut être gênant, mais pour la plupart, c'est à la fois possible et souhaitable. –

+0

@MilesSabin Merci pour la clarification! –