From F# to Scala – implicits

Read the whole series:

Part 1 — type infer­ence

Part 2 — traits

Part 3 — case class/object (ADTs)

Part 4 — apply & unap­ply func­tions

Part 5 — implic­its <- you’re here

Hav­ing looked at case class and extrac­tors recent­ly, the next log­i­cal thing would be par­tial func­tions. Since Andrea point­ed me to a real­ly well arti­cle on the sub­ject I don’t think there’s any­thing else for me to add, so instead, let’s look at Scala’s implic­its, which is a very pow­er­ful lan­guage fea­ture that enables some inter­est­ing pat­terns in Scala.


implicit operator in .Net

You can define both implic­it and explic­it oper­a­tors in C#, which allows you to either:

  • implic­it­ly con­verts a type to anoth­er in assign­ment, method argu­ment, etc.; or
  • explic­it­ly cast a type to anoth­er

F# on the oth­er hand, is a more strong­ly typed lan­guage and does not allow such implic­it type con­ver­sion. You can still imple­ment and use exist­ing implic­it oper­a­tors cre­at­ed in C#, which is avail­able to you as a sta­t­ic mem­ber op_Implicit on the type it’s defined on.

For exam­ple.

Addi­tion­al­ly, you can also cre­ate type exten­sions to add exten­sion meth­ods AND prop­er­ties to a type. Whilst this is the idiomat­ic F# way, these exten­sion mem­bers are only vis­i­ble to F# (and not to C#).


implicit in Scala

Where the implic­it oper­a­tor in .Net (or more specif­i­cal­ly, in C#) is con­cerned with type con­ver­sion, implic­it in Scala is far more gen­er­alised and pow­er­ful.

Scala’s implic­it comes in 3 flavours:

  • implic­it para­me­ters
  • implic­it con­ver­sions
  • implic­it class­es

implicit parameters

You can mark the last para­me­ter of a func­tion as implic­it, which tells the com­pil­er that the caller can omit the argu­ment and the com­pil­er should find a suit­able sub­sti­tute from the clo­sure.

For exam­ple, take the mul­ti­ply­Im­plic­it­ly func­tion below.

The last argu­ment is omit­ted at invo­ca­tion but the com­pil­er sees a suit­able sub­sti­tute — mult — in scope because:

  1. it’s the right type — Mul­ti­pli­er
  2. it’s declared as implic­it

and implic­it­ly applies it as the sec­ond argu­ment to com­plete the invo­ca­tion.

That’s right, only val/var/def that are declared as implic­it can be used as an implic­it argu­ment.

If mult was not declared as implic­it, then a com­pil­er error awaits you instead.

What if there are more than one match­ing implic­it val­ue in scope?

Then you also get a com­pil­er error.

Unsur­pris­ing­ly, implic­it var also works, and giv­en the muta­ble nature of var it means mul­ti­ply­Im­plic­it­ly can yield dif­fer­ent val­ue depend­ing on when it’s called.

Final­ly, you can also use an implic­it def (which you can think of as a prop­er­ty, it is eval­u­at­ed each time but it doesn’t have to be attached to an object).

A com­mon use case for implic­it para­me­ters is to implic­it­ly use the glob­al Exe­cu­tion­Con­text when work­ing with Scala’s Future. Sim­i­lar­ly, the Akka frame­work use implic­it to pass around Actor­Con­text and ActorSys­tem objects.

implicit conversions

What if you define a high­er-order func­tion that takes in anoth­er func­tion, f, as argu­ment, can f be cho­sen implic­it­ly as well?

Yes, it can. It is in fact a com­mon pat­tern to achieve implic­it type con­ver­sion (sim­i­lar to .Net’s implic­it oper­a­tor as we saw at the start of this post).

Notice in the above that show(“42”) com­piles even though we haven’t defined an implic­it func­tion of the sig­na­ture String => String. We have the built-in iden­ti­ty func­tion to thank for that.

Just before the Scala com­pil­er throws a typemis­match excep­tion it’ll look for suit­able implic­it con­ver­sion in scope and apply it. Which means, our implic­it con­ver­sions can be use­ful out­side of the show func­tion too.

And you’re pro­tect­ed by the same guar­an­tee that there can only be one match­ing implic­it func­tion in scope.

What if there’s a more gener­ic implic­it con­ver­sion with the sig­na­ture Any -> String, would the com­pil­er com­plain about ambigu­ous implic­it val­ues or is it smart enough to use int­ToStr for Int?

It’s smart enough and does the right thing.

implicit classes

Final­ly, we have implic­it class­es which allows you to imple­ment .Net style exten­sion meth­ods.

You must cre­ate the implic­it class inside anoth­er object/trait/class, and it

and the class can take only one non-implic­it argu­ment in the con­struc­tor.

Note that in addi­tion to exten­sion meth­ods, you can also cre­ate exten­sion val­ues and prop­er­ties with implic­it class. Which, as we men­tioned at the start of the post, is some­thing that you can also do with F#‘s type exten­sions mech­a­nism.