4

ToFunctorOps defines a lift method via the ToLiftV implicit, but I can't seem to make it find my functor instances:

import scalaz.std.option._
import scalaz.syntax.functor._
import scalaz.syntax.id._
import scalaz.syntax.std.option._

def inc(x: Int) = x + 1

1.some |> (inc _).lift

<console>:16: error: could not find implicit value for parameter F: scalaz.Functor[F]
              1.some |> (inc _).lift

The functor instance for option is visible but the compiler can't seem to find it. Any suggestions as to how I can fix this?

Hugh
  • 8,872
  • 2
  • 37
  • 42

2 Answers2

2

I don't understand exactly why this isn't working (and I've just asked a follow-up question about the part I don't understand), but I can offer three workarounds.

The first makes no sense to me and requires some deeper changes to your code and clunky syntax, so I'll only mention it in passing.

The second is to import the appropriate FunctorSyntax implicits (as opposed to the ToFunctorOps ones that aren't working properly):

scala> val of = implicitly[scalaz.Functor[Option]]
of: scalaz.Functor[Option] = scalaz.std.OptionInstances$$anon$1@377d4c39

scala> import of.functorSyntax._
import of.functorSyntax._

scala> 1.some |> (inc _).lift
res0: Option[Int] = Some(2)

But this requires you to import these implicits for every individual Functor you want to use them with, and isn't much better than just writing of lift inc.

The last requires a little more code but is more satisfying. You need the following new syntax trait, with a myLift method modeled of the lift in Function2Ops:

trait MyFunction1Syntax[A, R] extends scalaz.syntax.Ops[A => R] {
  def myLift[F[_]](implicit F: scalaz.Functor[F]) = F lift self
}

implicit def toMyFunction1Syntax[A, R](f: A => R) =
  new MyFunction1Syntax[A, R] { def self = f }

And now you can write the following:

scala> 1.some |> (inc _).myLift
res3: Option[Int] = Some(2)

It might be worth bringing this issue up on the Scalaz mailing list.

Community
  • 1
  • 1
Travis Brown
  • 138,631
  • 12
  • 375
  • 680
  • I don't understand your claim on the second workaround. These imports should suffice. 'import scalaz.std.AllInstances._' and 'import scalaz.syntax.functor._' – Yo Eight Nov 22 '12 at 22:55
  • 1
    @YoEight yep, that's the point of this question: they should, but they don't. – Hugh Nov 23 '12 at 00:25
  • 1
    That is bizarre behaviour - really nice digging. – Hugh Nov 23 '12 at 00:27
0

Your problem can be easily resolved like this

import scalaz.syntax.std.option._
import scalaz.std.option._
import scalaz.syntax.id._

implicit def liftIt[F[_], A, B](f: A => B)(implicit F: Functor[F]): F[A] => F[B] =
  F lift f

def inc(x: Int) = x + 1

2.some |> inc

The issue came from a LiftV trait used in FunctorSyntax. Frankly, I doubt it could have been useful for someone. In order to work, it has to be explicitly typed:

import scalaz.syntax.functor._

val f: LiftV[Option, Int, Int] = (inc _)

2.some |> f.lift  
Yo Eight
  • 467
  • 2
  • 5