我已经了解了如何在我自己的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。
答案 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))
}