这是代码:

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,已重命名。

09-05 08:12