14

I am new to Scala, and when I look at different projects, I see two styles for dealing with implicit arguments

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

and

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

Based off the type of both functions, they match. Is there a difference between the two? Why would you want to use implicitly over implicit arguments? In this simple example, it feels more verbose.

When I run the above in the REPL with something that doesn't have an implicit, I get the following errors

with implicit param

<console>:11: error: could not find implicit value for parameter m: Monoid[String]

and

with implicitly and a: Monoid

<console>:11: error: could not find implicit value for evidence parameter of type Monoid[String]
giampaolo
  • 6,906
  • 5
  • 45
  • 73
ekaqu
  • 2,038
  • 3
  • 24
  • 38

1 Answers1

15

In some circumstances, the implicit formal parameter is not directly used in the body of the method that takes it as an argument. Rather, it simply becomes an implicit val to be passed on to another method that requires an implicit parameter of the same (or a compatible) type. In that case, not having the overt implicit parameter list is convenient.

In other cases, the context bound notation, which is strictly syntactic sugar for an overt implicit parameter, is considered aesthetically desirable and even though the actual parameter is needed and hence the implicitly method must be used to get it is considered preferable.

Given that there is no semantic difference between the two, the choice is predicated on fairly subjective criteria.

Do whichever you like. Lastly note that changing from one to the other will not break any code nor would require recompilation (though I don't know if SBT is discriminting enough to forgo re-compiling code that can see the changed definition).

Randall Schulz
  • 26,420
  • 4
  • 61
  • 81
  • 1
    "note that changing from one to the other will not break any code nor would require recompilation": this is technically incorrect. It is entirely correct (though uncommon) to explicitly specify an implicit parameter as a *named parameter*. So you can do `sum(List(1,2,3))(m=someMonoidInstance)`. Replacing the implicit parameter in the declaration with a context bound will change the implicit parameter name from `m` to something like `evidence$1`, breaking the above call. Parameter names (including implicit ones) are part of the interface, for better but also for worse. Nitpicking, but still. – Régis Jean-Gilles Mar 26 '14 at 23:27
  • OK, OK… That is quite the nit! – Randall Schulz Mar 27 '14 at 00:34
  • "In other cases, the context bound notation (which is strictly syntactic sugar for an overt implicit parameter) is considered aesthetically desirable, even though the actual parameter is needed and hence the implicitly method must be used to get it." – RoyalCanadianKiltedYaksman May 19 '15 at 07:32