如何在地图函数中使用无形poly1

时间:2014-04-30 04:48:08

标签: scala shapeless

这是代码:

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)是如何工作的?

1 个答案:

答案 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(_) ,已重命名。