我想用隐式定义提升。假设我们有一个函数A => B,我想定义如何将它提升到Maybe,即Maybe[A] => Maybe[B]。
这可以通过隐式转换简单地完成。但是,如果我想对具有两个或更多参数的函数做同样的事情,我就有问题了。我知道的唯一解决方案是复制代码。
我想为具有任意数量的参数的任意函数实现这种提升而不重复。这在 Scala 中可行吗?
我想用隐式定义提升。假设我们有一个函数A => B,我想定义如何将它提升到Maybe,即Maybe[A] => Maybe[B]。
这可以通过隐式转换简单地完成。但是,如果我想对具有两个或更多参数的函数做同样的事情,我就有问题了。我知道的唯一解决方案是复制代码。
我想为具有任意数量的参数的任意函数实现这种提升而不重复。这在 Scala 中可行吗?
如果F
有可用的仿函数实例,则可以将任何函数提升A => B
到F[A] => F[B]
.
如果F
有可用的应用函子实例,则可以将任何函数提升A => B => C => .. => Z
到F[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
方法等Function2
,Function3
因为语法上较重的 curried 函数使用频率较低。在幕后,提升发生在Function1
s (即柯里化函数)中。
您可能还想查看Scalaz 源代码。