Special classes of Ad-hoc polymorphism

I have looked over the scalar tutorial .

From this link , I understand the following code:

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

      

But I don't understand the following code:

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

      

If we consider List(1, 2, 3, 4)

, A

is Int

.

So how can we A

a Monoid

and A

a Int

in def sum[A: Monoid](xs: List[A]): A = {

?

thank

+3


source to share


1 answer


The syntax A : X

is called "context bound" and is equivalent to getting an implicit type parameter X[A]

. That is, the following two declarations are the same:

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

      

However, the implicit parameter name is not available when using context boundaries, so you need to "restore" it if you need to use it directly. One way to do this is to use a method implicitly

as seen:

val m = implicitly[Monoid[A]]

      



Here's the definition implicitly

:

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

      

In any case, the two definitions you showed are pretty much the same. If you understand the first, just know that the second is identical, but written with a different syntax.

One final note on context bounds: It might seem silly to use context-specific syntax only to be used implicitly

afterwards to get the parameter name. But if you just need the implicit parameter to be passed as implicit to other methods - and therefore doesn't need to know the name - that makes the declarations a lot neat.

+6


source







All Articles