2012-07-08 14 views
9

implicitsでリフティングを定義したいと思います。関数A => Bがあると仮定し、それをMaybe [A] => Maybe [B]に持ち上げる方法を定義したいと思います。スカラのリフティング関数

これは暗黙的な変換で簡単に行うことができます。しかし、2つ以上のパラメータを持つ関数で同じことをしたいのであれば、私は問題があります。私が知っている唯一の解決策は、コードを複製することです。

任意の数のパラメータを持つ任意の関数に対して、このようなリフティングを重複なく実装したいと考えています。これはScalaでも可能ですか?

+2

これは価値があるかもしれません:http://blog.tmorris.net/lifting/ –

+0

http://www.scala-lang.org/api/current/index.html#scala.Function2を見てくださいタップル機能に気付く。 http://www.scala-lang.org/api/current/index.html#scala.Function$タップされたメソッドとuntupledメソッド。 – pedrofurla

答えて

18

Fにファンクタインスタンスがある場合、A => BF[A] => F[B]に持ち上げることができます。

Fに利用可能なファンクタインスタンスがある場合は、A => B => C => .. => ZF[A] => F[B] => F[C] => .. => F[Z]に持ち上げることができます。本質的には、適用可能なファンクタは、任意のアライドに対するファンクタの一般化です。

ファンクタと適用ファンクタherehereについて知ることができます。これらのアイデアをカバーする優れた講演もあります。this

Scalazライブラリは、これらの抽象化(とmore!)を提供します。

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 

syntactially重いあるカリー機能はあまり使用されているので、ScalazはFunction2Function3などにlift方法を朝飯前。背後では、持ち上げはFunction1(カルト機能)で行われます。

Scalaz source codeをご覧ください。

+1

奇妙なことに、 'foo.lift [Option]'はScalaz 7ではコンパイルされませんが、 'add.lift [Option]'は –

+1

です@NikitaVolkov、ちょうどここで推測して... 1. Functor [Option] .lift (foo) 'と' Applicative [Option] .lift2(add) 'が動作するかもしれません。現在、公開されている「拡張方法」が少なくなっています。 2.ほとんどの拡張メソッドは、 'scalaz.syntax'パッケージで利用できます。あなたが探している「リフト」がそこに横たわっているかもしれません。 – missingfaktor

+0

はScalaz 7.1とScala 2.11.5で動作するはずの上記コードですか? –