带函子的数值映射

Numeric Map Over With Functor

我想将 case class Bonus[A: Numeric](amt: A) 映射到 Functor 上,但它失败了。编译错误是

Error:(157, 69) could not find implicit value for evidence parameter of type Numeric[B] (No implicit Ordering defined for B.)
override def fmap[A, B](fa: Bonus[A])(f: A => B): Bonus[B] = Bonus(f(fa.amt))

总的来说,我想把Bonus中的参数类型固定为数字。我该如何解决?谢谢

代码片段,

trait Functor[F[_]] {
  def fmap[A, B](fa: F[A])(f: A => B): F[B]
}

def fmap[A, B, F[_]](fa: F[A])(f: A => B)(implicit ev: Functor[F]): F[B] = ev.fmap(fa)(f)

case class Bonus[A: Numeric](amt: A)

implicit val bonusFunctor = new Functor[Bonus] {
  override def fmap[A, B](fa: Bonus[A])(f: A => B): Bonus[B] = Bonus(f(fa.amt)) // error
}

fmap(Bonus(123))(_ * 2)

更新 1

谢谢 MarioDmytro 的回答。

Dmytro,你的答案与我在 https://users.scala-lang.org/t/how-to-add-type-constraint-to-functors-map-function/2055 中找到的完全一样。我放弃约束或使用约束 Functor 是有道理的。我接受了 Mario 的回答,因为它向我展示了一个替代解决方案,因为 Functor 是不可能的。

无法为任何类型构造函数定义 Functor 类型 class 的实例。

类型构造函数 F[_] 具有类型 class Functor 的实例这一事实意味着 对于任何 AB,有一个函数A => B,你知道如何将F[A]转换为F[B]

但是如何将 Bonus[A] 转换为 Bonus[B] 对于任何 A, B?

类型 Bonus[A]Bonus[B] 对任何 AB 都有意义,即使它们不是 Numeric,但会创建 Bonus[B] 通过构造函数仅对 B: Numeric.

有意义

要么删除 case class Bonus[A: Numeric](amt: A) 中的上下文绑定 Numeric,要么 Bonus 不是 Functor

如果您定义自己的类型class

trait NumericFunctor[F[_]] {
  def fmap[A: Numeric, B: Numeric](fa: F[A])(f: A => B): F[B]
}

它不是针对类型类别的标准函子,而是针对 Numeric 类型类别的自定义函子。

尝试

trait GFunctor[F[_], G[_]] {
  def fmap[A, B](fa: F[A])(f: A => B)(implicit ga: G[A], gb: G[B]) : F[B]
}

def fmap[A, B, F[_], G[_]](fa: F[A])(f: A => B)(implicit ev: GFunctor[F, G], ga: G[A], gb: G[B]): F[B] = ev.fmap(fa)(f)

case class Bonus[A: Numeric](amt: A)

implicit val bonusFunctor = new GFunctor[Bonus, Numeric] {
  override def fmap[A, B](fa: Bonus[A])(f: A => B)(implicit numA: Numeric[A], numbB: Numeric[B]): Bonus[B] = Bonus(f(fa.amt))
}

fmap(Bonus(123))(_ * 2)

输出

res0: Bonus[Int] = Bonus(246)

请注意我们如何通过

让我们的类型类解决方案意识到 AB 的进一步界限
(implicit ga: G[A], gb: G[B])