将双射提升为仿函数

时间:2013-10-18 17:18:45

标签: scala functor scalaz scalaz7 bijection

也许我错过了一些明显的东西,但我正在尝试清理一个使用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]之间的双射。我们可以轻松编写一个提供此功能的隐式类(实际上我们也可以使它适用于任何仿函数):

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.Bijectionbimap的直接翻译。 Scalaz的双射也有一个名为bimap的方法,但它有一个更繁忙的类型,似乎没有以任何明显的方式做我想要的。

现在我们可以写下以下内容:

fb.liftInto[List]

我们得到了我们需要的双射。

我是否遗漏了一些抽象概念,这使我能够更加干净地编写Scalaz 7中已经提供的用于双射的函数和实例?

1 个答案:

答案 0 :(得分:3)

引用Twitter Lars Hupel中的in response to this question

  

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

  

相关:T的{​​{1}}部分可能不对。它可能需要重写为看起来像Haskell版本。

所以答案显然不是,我没有遗漏任何东西 - 这实际上是当前API的一个空白,可能会在未来的Scalaz版本中修复。