3

我看了scalaz 教程

从此链接,我了解以下代码:

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

那么我们如何才能拥有A一个MonoidA一个Int indef sum[A: Monoid](xs: List[A]): A = {呢?

谢谢

4

1 回答 1

6

该语法A : X称为“上下文绑定”,它等效于接收类型的隐式参数X[A]。即以下两个声明是相同的:

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

但是,使用上下文边界时,隐式参数的名称是不可用的,因此如果需要直接使用它,则需要“检索”它。一种方法是使用该implicitly方法,如下所示:

val m = implicitly[Monoid[A]]

这是 的定义implicitly

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

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

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

于 2014-08-31T17:58:27.093 回答