2016-09-30 1 views
3

http://scastie.org/22713carte HList par défaut

copie locale:

/*** 
scalaVersion := "2.11.8" 
addCompilerPlugin("org.spire-math" %% "kind-projector" % "0.7.1") 
libraryDependencies ++= { 
    val shapelessVersion = "2.2.5" 
    Seq(
    "com.chuusai" %% "shapeless" % shapelessVersion 
) 
} 
*/ 

import shapeless._ 

case class Foo() 

trait Wrapper 

case class S(s: String) extends Wrapper 
case class I(i: Int) extends Wrapper 

object Main extends App { 
    object wrap extends Poly1 { 
    implicit def caseString = at[String](S.apply) 
    implicit def caseInt = at[Int](I.apply) 
    implicit def caseOther[T] = at[T](identity) 
    } 

    type A = Foo :: String :: HNil 
    type B = Foo :: Int :: HNil 
    type Out = Foo :: Wrapper :: HNil 

    val a: A = Foo() :: "foo" :: HNil 
    val b: B = Foo() :: 42 :: HNil 

    val aw: Out = a.map(wrap) 
    val bw: Out = b.map(wrap) 

} 

Erreurs:

[error] /tmp/renderercqsCBmArxo/src/main/scala/test.scala:56: could not find implicit value for parameter mapper: shapeless.ops.hlist.Mapper[Main.wrap.type,Main.A] 
[error] val aw: Out = a.map(wrap) 
[error]     ^
[error] /tmp/renderercqsCBmArxo/src/main/scala/test.scala:57: could not find implicit value for parameter mapper: shapeless.ops.hlist.Mapper[Main.wrap.type,Main.B] 
[error] val bw: Out = b.map(wrap) 
[error]     ^
[error] two errors found 
[error] (compile:compileIncremental) Compilation failed 

Comment puis-je changer ce seul dernier élément dans l'autre?

Répondre

5

Shapeless de Poly est vraiment juste une façon de regrouper certains cas implicites qui décrivent ce qui devrait arriver à différents types, de sorte que vous pouvez utiliser les mêmes astuces de priorités implicites que vous souhaitez utiliser dans d'autres situations Scala:

object wrap extends LowPriorityWrapCases { 
    implicit val caseString = at[String](S.apply) 
    implicit val caseInt = at[Int](I.apply) 
} 

trait LowPriorityWrapCases extends Poly1 { 
    implicit def caseOther[T] = at[T](identity) 
} 

Cela se traduira par une recherche implicite vérifiant les cas spécifiques d'abord et seulement alors tomber dans le cas par défaut, au lieu de simplement lever les mains en raison de l'ambiguïté si la liste a un élément String ou Int.

Comme une note de côté, je vous suggère de fournir des annotations de type explicites ici:

object wrap extends LowPriorityWrapCases { 
    implicit val caseString: Case.Aux[String, S] = at[String](S.apply) 
    implicit val caseInt: Case.Aux[Int, I] = at[Int](I.apply) 
} 

trait LowPriorityWrapCases extends Poly1 { 
    implicit def caseOther[T]: Case.Aux[T, T] = at[T](identity) 
} 

Il est un peu plus bruyant, mais il peut vous sauver de certains ennuyeux et difficile à des problèmes de débogage.

+0

http://scastie.org/22716 – Reactormonk