也许我没有看到显而易见的事情,但我正在尝试清理一个使用Scalaz 7的项目中的一些样板文件,并且我没有找到一个似乎非常简单和可能有用的拼图。
假设我们有两种类型之间的双向对应关系:
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)
)
现在假设我们发现需要在 List[Foo]
和 List[Bar]
之间建立一个双射关系。我们可以轻松地编写一个隐式类来提供这个功能(事实上,我们可能会让它适用于任何函子):
def fromG[B](implicit G: Functor[F], ev: A =:= F[B]): F[A] = G.map(ev(list.head))(Function.const(list)) } ```
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
)
}
请注意,这只是将Haskell的Data.Bijection
中的bimap
直接翻译而来。Scalaz的bijections也有一个名为bimap
的方法,但它的类型更加复杂,并且似乎没有以任何明显的方式实现我想要的功能。
现在我们只需要编写以下内容:
fb.liftInto[List]
我们已经拥有了所需的双射。
我是否漏掉了一些抽象概念,能够让我在Scalaz 7中使用已提供的双射函数和实例更加简洁地编写此代码?