9

I want to define lifting with implicits. Suppose we have a function A => B, I want to define how to lift it to Maybe, i.e. Maybe[A] => Maybe[B].

This can be simply done with implicit conversions. However, if I want to do the same with functions with two or more parameters, I have a problem. The only solutionI know is to duplicate the code.

I want to implement such lifting for arbitrary functions with any number of parameters without duplication. Is this possible in Scala?

2

1 Answer 1

18

If F has a functor instance available, it's possible to lift any function A => B to F[A] => F[B].

If F has an applicative functor instance available, it's possible to lift any function A => B => C => .. => Z to F[A] => F[B] => F[C] => .. => F[Z]. Essentially, applicative functor is a generalization of functor for arbitrary arity.

You can learn about functor and applicative functors here and here. There is also this excellent talk which covers these ideas.

Scalaz library provides these abstractions (and 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 

Scalaz pimps lift method on Function2, Function3 etc because curried functions being syntactially heavier are used less often. Behind the scenes, the lifting happens with Function1s (i.e. curried functions).

You might also want to take a look at Scalaz source code.

Sign up to request clarification or add additional context in comments.

3 Comments

Oddly enough foo.lift[Option] doesn't compile with Scalaz 7, but add.lift[Option] does
@NikitaVolkov, Just making a guess here... 1. Functor[Option].lift(foo) and Applicative[Option].lift2(add) might work. There are less "extension methods" out in the open now. 2. Most extension methods are still available in a package scalaz.syntax. The lift you are looking for might be lying there.
is the above code supposed to work on Scalaz 7.1 and Scala 2.11.5?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.