9

我想用隐式定义提升。假设我们有一个函数A => B,我想定义如何将它提升到Maybe,即Maybe[A] => Maybe[B]。

这可以通过隐式转换简单地完成。但是,如果我想对具有两个或更多参数的函数做同样的事情,我就有问题了。我知道的唯一解决方案是复制代码。

我想为具有任意数量的参数的任意函数实现这种提升而不重复。这在 Scala 中可行吗?

4

1 回答 1

18

如果F有可用的仿函数实例,则可以将任何函数提升A => BF[A] => F[B].

如果F有可用的应用函子实例,则可以将任何函数提升A => B => C => .. => ZF[A] => F[B] => F[C] => .. => F[Z]. 本质上,应用函子是函子对任意数量的推广。

您可以在此处此处了解函子和应用函子。还有一篇精彩的演讲涵盖了这些想法。

Scalaz 库提供了这些抽象(以及更多!)。

import scalaz._
import Scalaz._

scala> val foo: Int => String = _.toString
foo: Int => String = <function1>

scala> foo.lift[Option]
res0: Option[Int] => Option[String] = <function1>

scala> res0(Some(3))
res1: Option[String] = Some(3)

scala> res0(None)
res2: Option[String] = None

scala> val add: (Int, Int) => Int = _ + _
add: (Int, Int) => Int = <function2>

scala> add.lift[Option]
res3: (Option[Int], Option[Int]) => Option[Int] = <function2>

scala> res3(Some(2), Some(1))
res4: Option[Int] = Some(3)

scala> res3(Some(2), None)
res5: Option[Int] = None

scala> res3(None, None)
res6: Option[Int] = None

Scalaz pimpslift方法等Function2Function3因为语法上较重的 curried 函数使用频率较低。在幕后,提升发生在Function1s (即柯里化函数)中。

您可能还想查看Scalaz 源代码

于 2012-07-08T22:11:46.577 回答