cch*_*son 3 scala typeclass adhoc-polymorphism
我看了一下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
Run Code Online (Sandbox Code Playgroud)
但我不明白以下代码:
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
Run Code Online (Sandbox Code Playgroud)
如果我们考虑List(1, 2, 3, 4)
,A
是一个Int
.
那么怎样才能拥有A
一个Monoid
和A
一个Int
在def sum[A: Monoid](xs: List[A]): A = {
?
谢谢
语法A : X
称为"上下文绑定",它等同于接收类型的隐式参数X[A]
.也就是说,以下两个声明是相同的:
def sum[A: Monoid](xs: List[A]): A
def sum[A](xs: List[A])(implicit $ev0: Monoid[A]): A
Run Code Online (Sandbox Code Playgroud)
但是,使用上下文边界时隐式参数的名称不可用,因此如果需要直接使用它,则需要"检索"它.一种方法是使用该implicitly
方法,如下所示:
val m = implicitly[Monoid[A]]
Run Code Online (Sandbox Code Playgroud)
这是以下定义implicitly
:
def implicitly[T](implicit v: T): T = v
Run Code Online (Sandbox Code Playgroud)
无论如何,您展示的两个定义几乎相同.如果你理解第一个,只要知道第二个是相同的,但用不同的语法编写.
关于上下文边界的最后一点说明:使用上下文绑定语法只是implicitly
为了获取参数的名称后使用它似乎很愚蠢.但是如果你只需要隐式参数作为隐式传递给其他方法 - 因此,不需要知道名称 - 它会使声明更整洁.