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?
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 ofBijectionT
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.