2012-07-08 71 views
9

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

这可以通过隐式转换简单完成。但是,如果我想对具有两个或更多参数的函数执行相同的操作,则会出现问题。我知道的唯一解决方案是复制代码。

我想用任意数量的参数来实现这种提升任意函数而没有重复。这可能在斯卡拉?

+2

这可能值得一看:http://blog.tmorris.net/lifting/ – 2012-07-08 21:54:25

+0

请看http://www.scala-lang.org/api/current/index.html#scala.Function2 ,注意tupled函数。另外http://www.scala-lang.org/api/current/index.html#scala.Function$元组和未添加的方法。 – pedrofurla 2012-07-08 22:07:29

回答

18

如果F有一个函子实例可用,可以将任何函数A => B提升为F[A] => F[B]

如果F有一个可用的函数实例,可以将任何函数A => B => C => .. => Z提升为F[A] => F[B] => F[C] => .. => F[Z]。从本质上讲,应用仿函数是任意仿函数的泛函。

您可以了解仿函数和应用仿函数herehere。涵盖这些想法的还有this优秀的演讲。

斯卡拉斯图书馆提供这些抽象(和更多!)。

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上皮条客Function2lift方法,Function3等因为是syntactially较重咖喱功能不经常使用。在幕后,提升发生在Function1(即咖喱功能)上。

您可能还想看看Scalaz source code

+1

奇怪的是'foo.lift [Option]'不能用Scalaz 7编译,但'add.lift [Option]'确实是 – 2012-09-17 12:47:20

+1

@NikitaVolkov,只是在这里猜测...... 1. Functor [Option] .lift (foo)'和'Applicative [Option] .lift2(add)'可能有效。现在公开的“扩展方法”较少。 2.大多数扩展方法仍然可以在'scalaz.syntax'包中找到。你正在寻找的'lift'可能会躺在那里。 – missingfaktor 2012-09-17 13:34:37

+0

是上面的代码应该在Scalaz 7.1和Scala 2.11.5上工作吗? – 2015-01-21 17:15:21