将双射映射提升为函子

21

也许我没有看到显而易见的事情,但我正在尝试清理一个使用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] 之间建立一个双射关系。我们可以轻松地编写一个隐式类来提供这个功能(事实上,我们可能会让它适用于任何函子):

```scala implicit class ListIsomorphism[F[_], A](list: List[A]) { def toG[B](implicit G: Functor[F], ev: A =:= F[B]): F[A] = G.map(ev(list.head))(Function.const(list))
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中使用已提供的双射函数和实例更加简洁地编写此代码?

1个回答

3

引用Lars Hupel在Twitter上回答这个问题的话:

我不知道我们的bimap是什么或者它应该做什么。

还有:

相关: BijectionT中的T部分可能是错误的。它可能需要重写成类似于Haskell版本的样子。

所以答案显然是否定的,我没有漏掉任何内容——这实际上是当前API中的一个缺陷,在未来的Scalaz版本中可能会被修复。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接