这是代码:
object inc extends Poly1 {
implicit val caseInt = at[Int]{_ + 1}
implicit def default[T] = at[T](identity)
}
println(List(3).map(inc))
println(List("3").map(inc))
我的问题是如何将poly1混合到map函数中。 TraversableLike定义地图签名。 Map [B,That](f:A => B),“那”将由CanBuildFrom提供,所以我的困惑是关于A => B,我看了Poly1的源代码,没有映射,如何List(3).map(inc)有效吗?
最佳答案
这在http://www.chuusai.com/2012/05/10/shapeless-polymorphic-function-values-2/中进行了解释;寻找有关polyToMono
的部分。
核心思想是,尽管Poly1
无法扩展scala.Function1
,但是Shapeless提供了隐式转换,因此可以在期望使用普通单态函数的情况下(例如,调用List.map
时)提供多态函数。
为了使其适用于像Int
这样的普通类型(如您的示例中)和参数化类型,还需要一些额外的技巧。这是通过将Int
包装为Id[Int]
(其中Id
是类型级别的标识函数)来完成的,将未参数化的情况减少为参数化的情况。
但是这些博客文章来自2012年,2014年我们如今拥有的Shapeless 2.0有时会有所不同。如有疑问,请查阅Shapeless 2.0源代码。
2.0源码没有任何叫做polyToMono
的东西。去哪了
碰巧,reify
有助于调查这些“这到底是怎么编译的?”输入问题:
scala> reflect.runtime.universe.reify(List(3).map(inc))
res1: reflect.runtime.universe.Expr[List[inc.caseInt.Result]] =
Expr[List[inc.caseInt.Result]](
List.apply(3).map(Poly.inst1($read.inc)(this.inc.caseInt))(
List.canBuildFrom))
所以
Poly.inst1
似乎是这里的关键,是的,在https://github.com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/poly.scala中,我们看到:implicit def inst1[F[_], G[_], T](f : F ~> G) : F[T] => G[T] = f(_)
这只是博客文章中的
polyToMono
,已重命名。