使用默认映射 HList
map HList with default
本地副本:
/***
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)
}
错误:
[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
如何将最后一个元素更改为另一个元素?
Shapeless 的 Poly
实际上只是一种捆绑一些隐式实例的方法,这些实例描述了不同类型应该发生什么,因此您可以使用与 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)
}
这将导致隐式搜索首先检查特定情况,然后才进入默认情况,而不是如果 hlist 有 String
或 [=14,就会因为歧义而简单地举起手来=]元素.
作为旁注,我建议在此处提供显式类型注释:
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)
}
它有点吵,但它可以让您避免一些烦人且难以调试的问题。
本地副本:
/***
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)
}
错误:
[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
如何将最后一个元素更改为另一个元素?
Shapeless 的 Poly
实际上只是一种捆绑一些隐式实例的方法,这些实例描述了不同类型应该发生什么,因此您可以使用与 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)
}
这将导致隐式搜索首先检查特定情况,然后才进入默认情况,而不是如果 hlist 有 String
或 [=14,就会因为歧义而简单地举起手来=]元素.
作为旁注,我建议在此处提供显式类型注释:
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)
}
它有点吵,但它可以让您避免一些烦人且难以调试的问题。