这是代码:
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混合到地图功能中。 TraversableLike定义了地图签名。映射[B,那](f:A => B),"那"将由CanBuildFrom提供,所以我的困惑是关于A => B,我看一下Poly1的源代码,没有映射,这个List(3).map(inc)是如何工作的?
答案 0 :(得分:4)
http://www.chuusai.com/2012/05/10/shapeless-polymorphic-function-values-2/解释了这一点;查找关于polyToMono
的部分。
核心思想是虽然Poly1
无法扩展scala.Function1
,但Shapeless提供了隐式转换,因此可以在需要普通单态函数的情况下提供多态函数,例如调用{ {1}}。
还需要一些额外的技巧才能使其适用于List.map
(如示例中)和参数化类型等普通类型。这是通过将Int
包装为Int
(其中Id[Int]
是类型级别标识函数)来完成的,将未参数化的大小写减少为参数化大小写。
但是这些博客文章是从2012年开始的,而且我们今天在2014年的Shapeless 2.0中的内容有时会有所不同。如有疑问,请参阅Shapeless 2.0源代码。
2.0来源没有任何名为Id
的内容。它去了哪里?
碰巧,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))
似乎是关键所在,是的,我们在https://github.com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/poly.scala看到了:
Poly.inst1
这只是博文中的implicit def inst1[F[_], G[_], T](f : F ~> G) : F[T] => G[T] = f(_)
,已重命名。