【问题标题】:Transform an M[A => B] to an A => M[B]将 M[A => B] 转换为 A => M[B]
【发布时间】:2013-12-18 01:21:25
【问题描述】:

Scala 或 Scalaz 中是否存在实用程序来将函数容器/集合转换为从相同输入映射到集合输出值的函数?签名看起来像

def transform[M[_], A, B](m: M[A => B]): A => M[B] = ???

这是 List 容器的示例实现:

def transform[A, B](fs: List[A => B]): A => List[B] = x =>
  fs.foldRight[List[B]](Nil) {
    (f, acc) => f(x) :: acc
  }

理想情况下,这适用于任何函数容器,包括函数元组、Option[Function1[A, B]],甚至是TupleN[Option[Function1[A, B]], ...]

编辑:

我刚刚意识到(至少对于 List 的特殊情况)map 函数有效:

    def transform[A, B](fs: List[A => B]): A => List[B] = x => fs map (_(x))

这可以推广到任何具有适当语义的 map 函数的东西。什么是合适的类型类?

【问题讨论】:

    标签: scala functional-programming scalaz


    【解决方案1】:

    假设 M 是一个 Functor,则 scalaz 的 Functor 中的 mapply 具有类似的类型签名:

    def mapply[A, B](a: A)(f: F[A => B]): F[B] = map(f)((ff: A => B) => ff(a))
    

    所以你可以这样写转换:

    def transform[M[_],A,B](m: M[A => B])(implicit f:Functor[M]):A => M[B] = f.mapply(_)(m)
    

    编辑:使用FunctorSyntax 的功能的另一个实现:

    def transform[M[_]:Functor,A,B](m: M[A => B]):A => M[B] = _.mapply(m)
    

    【讨论】:

    • 有趣。我刚刚发现了 Functor 并在下面添加了一个答案。使用mapply 而不是map 有什么好处吗?
    • 它们是两个不同的函数,但是mapply可以写成map。如果您将fs 更改为f 并在您的实现中扩展占位符,您会发现它与mapply 的实现基本相同:f map ((ff: A => B) => ff(a)),与map(f)((ff: A => B) => ff(a)) 相比
    • 我之前的评论是针对“mapmapply 之间的区别是什么”而写的,这就是我记得您最初评论的措辞。好处是代码重用(见编辑)。 transform 本质上是 mapply,但参数已重新排列。
    • 是的,我对其进行了重新措辞,以使我实际要求的内容更加清晰。特别是,我不喜欢为 Functor 显式添加参数列表的冗长,但我确实喜欢它更接近无点样式的方式。您的最新编辑绝对是最干净、最清晰的实现。
    【解决方案2】:

    我搜索了 Scalaz 源代码,看起来 Functor 可以解决问题:

    def transform[M[_]: Functor, A, B](fs: M[A => B]): A => M[B] = a => fs map (_(a))
    

    【讨论】:

      猜你喜欢
      • 2014-03-23
      • 2015-01-31
      • 1970-01-01
      • 2012-04-07
      • 2021-10-15
      • 2018-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多