【发布时间】:2017-02-19 05:01:45
【问题描述】:
我的一个项目混合使用了一些似乎不能很好地混合在一起的 scala 功能:
- 类型类和无形自动类型类实例派生
- 隐式转换(为具有类型类实例的类型添加有用的语法)
- 默认参数,因为即使它们通常是坏事,但在这里太方便了
我遇到的问题是类型类实例派生失败,如果:
- 未明确指定默认参数
- 无形推导使用
Lazy
这是我可以编写的用于重现该问题的尽可能少的代码:
Show.scala
import shapeless._
trait Show[A] {
def show(a: A): String
}
object Show {
def from[A](f: A => String): Show[A] = new Show[A] {
override def show(a: A) = f(a)
}
implicit val intShow: Show[Int] = Show.from(_.toString)
implicit def singletonShow[A](implicit
sa: Show[A]
): Show[A :: HNil] = Show.from {
case (a :: HNil) => sa.show(a)
}
implicit def singletonCaseClassShow[A, H <: HList](implicit
gen: Generic.Aux[A, H],
sh: Lazy[Show[H]]
): Show[A] = Show.from {
a => sh.value.show(gen.to(a))
}
}
运行.scala
object Run extends App {
implicit class ShowOps[A](val a: A) extends AnyVal {
def show(header: String = "> ")(implicit sa: Show[A]): String =
header + sa.show(a)
}
case class Foo(i: Int)
println(Foo(12).show())
}
编译失败,错误信息如下:
Run.scala:10: could not find implicit value for parameter sa: Show[Run.Foo]
[error] println(Foo(12).show())
编译错误由以下任一方法修复:
- 在
Run.scala中将header参数显式传递给show - 将
Lazy包装器移除到Show.scala中的隐式Show[H]
我必须承认我在这里完全不知所措。我很想了解会发生什么,如果存在解决方法,我很想知道。
【问题讨论】: