scala - Ad-hoc 多态性 - 类型类

标签 scala typeclass adhoc-polymorphism

我查看了 scalaz tutorial .

来自 this link ,我理解以下代码:

scala> def sum[A](xs: List[A])(implicit m: Monoid[A]): A = xs.foldLeft(m.mzero)(m.mappend)
sum: [A](xs: List[A])(implicit m: Monoid[A])A

scala> implicit val intMonoid = IntMonoid
intMonoid: IntMonoid.type = IntMonoid$@3387dfac

scala> sum(List(1, 2, 3, 4))
res9: Int = 10

但是我不明白下面的代码:

scala> def sum[A: Monoid](xs: List[A]): A = {
         val m = implicitly[Monoid[A]]
         xs.foldLeft(m.mzero)(m.mappend)
       }
sum: [A](xs: List[A])(implicit evidence$1: Monoid[A])A

scala> sum(List(1, 2, 3, 4))
res10: Int = 10

如果我们考虑 List(1, 2, 3, 4)A 是一个 Int

那么我们如何在 def sum[ A: Monoid](xs: List[A]): A = { ?

谢谢

最佳答案

语法 A : X 被称为“上下文绑定(bind)”,它等同于接收类型为 X[A] 的隐式参数。即下面两个声明是一样的:

def sum[A: Monoid](xs: List[A]): A
def sum[A](xs: List[A])(implicit $ev0: Monoid[A]): A

但是隐式参数的名称在使用context bounds时是不可用的,所以如果需要直接使用则需要“取回”。一种方法是使用 implicitly 方法,如下所示:

val m = implicitly[Monoid[A]]

下面是implicitly的定义:

def implicitly[T](implicit v: T): T = v

无论如何,您显示的两个定义几乎相同。如果您理解第一个,就知道第二个是相同的,但用不同的语法编写。

关于上下文边界的最后一点注意事项:使用上下文边界语法只是为了在之后使用隐式 来获取参数名称,这似乎很愚蠢。但是,如果您只需要将隐式参数作为隐式传递给其他方法——因此不需要知道名称——,它会使声明更加简洁。

关于scala - Ad-hoc 多态性 - 类型类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25594568/

相关文章:

java - 包包含具有相同名称的对象和包

scala - Scalaz7中的“序列”在哪里

monads - 在 Coq 中定义 Maybe monad

scala - Scala 中 Ad-hoc 多态性和参数多态性的区别

haskell - 在临时多态函数和参数多态函数之间转换的好方法

python - 为什么 spark 在我的 PC 上总是使用单核?

scala - 如何获取Play和Scala中的所有请求参数

scala - 使用绑定(bind)在类类型参数中的上下文

haskell - Haskell 中的孤立实例