Scala 隐式用于任意深度的仿函数组合

标签 scala scalaz

我正在尝试为现有类提供扩展方法 Elem在斯卡拉。但是,我也希望任何 M[Elem] 都可以使用这些操作。 ,只要一个Scalaz FunctorM在范围内。行为总是通过使用 map 将操作应用于仿函数。 .

import scalaz._
import Scalaz._

class Elem

implicit class Ops[F[_]: Functor, A <% Elem](self: F[A]) {
  def foo = self.map(_ => "bar")
}

val elem = new Elem

// TODO (nice to have): can we avoid this "explicit implicit" conversion?
implicit def idOps[A <% Elem](self: A) = new Ops[Id, A](self)

elem.foo                        // bar
Option(elem).foo                // Some(bar)
List(elem).foo                  // List(bar)

我想更进一步,让我的扩展方法可用于任意深度的仿函数,例如 List[Option[Elem]]Option[Option[Option[Elem]]] .我能够写一个隐式提供 Ops对于两个仿函数的组合,但我无法将其推广到任意嵌套深度:
// TODO: can we improve this to provide arbitrarily deep functor composition?
implicit def compositeOps[F[_]: Functor, G[_]: Functor, A <% Elem](self: F[G[A]]) = {
  implicit val FG = implicitly[Functor[F]].compose[G]
  new Ops[({ type FG[X] = F[G[X]] })#FG, A](self)
}

List(Option(elem)).foo          // List(Some(bar))
Option(List(Option(elem))).foo  // doesn't compile

有没有办法实现这一目标?

最佳答案

您可以递归地使用隐式助手:

sealed trait Helper[FA] {
  type A
  type F[_]
  def w(fa: FA): F[A]
  val f: Functor[F]
}
trait Helper1 {
  implicit def nil[A] = new Helper[A] {
    type A = A
    type F[X] = X
    def w(a: A) = a
    val f = implicitly[Functor[Id]]
  }
}
object Helper extends Helper1 {
  implicit def cons[FA1, RA](implicit u: Unapply[Functor, FA1]{type A = RA},
    rest: Helper[RA]) = new Helper[FA1] {
    type A = rest.A
    type F[X] = u.M[rest.F[X]]
    def w(fa: FA1) = u.TC.map(u.apply(fa))(rest.w)
    val f = rest.f.compose(u.TC) //or the other way around, I can never remember
  }
}
implicit def compositeOps[FA, A1](self: FA)(
  implicit helper: Helper[FA]{type A = A1}, conv: A1 => Elem) = {
    implicit val FG = helper.f
    new Ops[helper.F, helper.A](helper.w(self))
}

关于Scala 隐式用于任意深度的仿函数组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26834230/

相关文章:

scala - 从 scalaz 导入 `IO`

scala - 如何将 F[A\/B] 拆分为 (F[A], F[B])

scala - 是否有可以与组合器组合的最大数量的验证?

Scalaz Bind[Seq] 类型类

scala - 如何匹配函数签名而不在 Scala 中收到类型删除编译器警告

scala - Spark : PageRank example when iteration too large throws stackoverflowError

scala - _::在 Scala 中是什么意思?

scala - Spark/Scala在多个列上使用相同的函数重复调用withColumn()

scala - 通过使用 scalaz 的函数的 Option[Int] 对的条件映射

json - 如何在 JSON : SPARK Scala 中使用 read.schema 仅指定特定字段