我想用implicits来定义提升。假设我们有一个函数A => B,我想定义如何将它提升到Maybe,即Maybe [A] =>也许[B]。
这可以通过隐式转换完成。但是,如果我想对具有两个或更多参数的函数执行相同操作,则会出现问题。我知道的唯一解决方案是复制代码。
我想用任意数量的参数实现任意函数的这种提升而不重复。这在Scala中是否可行?
答案 0 :(得分:18)
如果F
有可用的仿函数实例,则可以将任何函数A => B
提升为F[A] => F[B]
。
如果F
有可用的应用仿函数实例,则可以将任何函数A => B => C => .. => Z
提升为F[A] => F[B] => F[C] => .. => F[Z]
。从本质上讲,applicative functor是对任意arity的仿函数的推广。
您可以了解仿函数和应用仿函数here和here。还有this优秀的演讲,涵盖了这些想法。
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
lift
,Function2
等上的Scalaz pimps Function3
方法,因为混合函数较多的咖喱函数使用频率较低。在幕后,提升发生在Function1
s(即curried函数)。
您可能还想查看Scalaz source code。