Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 737
Travis Brown Avatar asked Oct 18 '13 17:10

Travis Brown


1 Answers

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.

like image 89
Travis Brown Avatar answered Oct 07 '22 16:10

Travis Brown