我可以在MyCaseClass [A,B]上创建一个Functor吗?

时间:2015-06-07 00:08:54

标签: scala functor scalaz

我已经了解了如何在我自己的case类中创建一个Functor,当它的参数类型为A时。

case class MyCaseClass[A](a: A, b: A)
val local = MyCaseClass[String]("One", "Two")

implicit val myCaseClassFunctor = new Functor[MyCaseClass]{
  def map[A, B](fa: MyCaseClass[A])(f: A => B) = MyCaseClass(f(fa.a), f(fa.b))
}
val F = Functor[MyCaseClass]

val res = F.map(local)(_ + ".")
println(res)

在现实生活中的问题中,案例类不会由相同类型但不同的参数组成。

如果案件分支变得像

那样简单
case class MyCaseClass[A, B](a: A, b: B)

可以为它构建一个Functor吗?

我的猜测是我不可能因为地图的定义非常清楚,因为它的类型参数

def map[A, B]

但是我必须问,因为这是我第一次编写Functor。

2 个答案:

答案 0 :(得分:3)

对于具有两个参数的类,有两个Functor可能:一个映射第一个字段,另一个映射第二个字段。虽然这是解决方案,但我建议定义一个Bifunctor,因为它更通用:

implicit val bifunctor = new Bifunctor[MyCaseClass] {
  /** `map` over both type parameters. */
  def bimap[A, B, C, D](fab: MyCaseClass[A, B])(f: A => C, g: B => D): MyCaseClass[A, B] =
    MaCaseClass(f(fab.a), g(fab.b))
}

拥有Bifunctor个实例,您可以轻松获得右侧参数左侧的Functor

implicit def functor[X] = bifunctor.leftFunctor[X]
// or
implicit def functor[X] = bifunctor.rightFunctor[X]

答案 1 :(得分:1)

Functor需要具有单个类型参数的类型,是的,但您可以使用所谓的type lambdas

implicit def myCaseClassFunctor[C] = new Functor[({type f[X] = MyCaseClass[C, X]})#f]{
  def map[A,B](fa: MyCaseClass[C,A])(f:A=>B) = MyCaseClass(fa.a, f(fa.b))
}