scalafunctorscalazscalaz7bijection

Lifting a bijection into a functor


Maybe I'm missing something obvious, but I'm trying to clean up some boilerplate in a project that uses Scalaz 7, and I'm not finding one particular puzzle piece that seems pretty simple and possibly useful.

Suppose we have a bijection between two types:

case class Foo(x: Int)
case class Bar(i: Int)

import scalaz._, Scalaz._, BijectionT._

val fb: Foo <@> Bar = bijection[Id, Id, Foo, Bar](
  foo => Bar(foo.x),
  bar => Foo(bar.i)
)

Now suppose we find that we need a bijection between List[Foo] and List[Bar]. We can easily write an implicit class that provides this functionality (in fact we may as well make it work for any functor):

implicit class BijectionLifter[A, B](val bij: A <@> B) extends AnyVal {
  def liftInto[F[_]: Functor]: F[A] <@> F[B] = bijection[Id, Id, F[A], F[B]](
    _ map bij.to,
    _ map bij.from
  )
}

Note that this is a straightforward translation of bimap from Haskell's Data.Bijection. Scalaz's bijection also has a method named bimap, but it has a much busier type and doesn't seem to do what I want in any obvious way.

Now we can just write the following:

fb.liftInto[List]

And we've got the bijection we need.

Am I missing some abstraction that would make it possible for me to write this more cleanly with the functions and instances already provided for bijections in Scalaz 7?


Solution

  • To quote Lars Hupel from Twitter in response to this question:

    I have no idea what our bimap is or what's it supposed to do.

    And:

    Related: The T part of BijectionT is probably wrong. It probably needs to be rewritten to look like the Haskell version.

    So the answer is apparently no, I wasn't missing anything—this actually is a gap in the current API that will probably be fixed in a future Scalaz version.