Implicit Type Conversion

Scala 3.0 allows programmers to implicitly convert data of one type into another.

Consider the following partial implementation of complex numbers: Complex.scala.

Notes

·       Complex defines + and unary negation operators.

·       When a Double or Int is used in a context where a Complex was expected, the Scala compiler will automatically change them into complex numbers with:

given Conversion[Double, Complex] = Complex(_)
given Conversion[Int, Complex] = Complex(_)

Contextual Abstractions

Context abstraction is a new feature in Scala 3 and is best explained here.

My take: We have seen in our discussion of static vs. dynamic scoping that a function needs to either know its defining environment (static scoping) or its calling environment (dynamic scoping) in order to look up non-local references. Context abstraction takes this a step further. A context is like an environment.

abstraction is a function that can resolve

Any object can be a context. Intuitively, a context contains configuration data such as port numbers, file locations, and constants. A function may depend on a context. In this case we might consider making the context an explicit parameter:

def f(x: T, c: Context)= ...

A context abstraction f2 of f treats c as an implicit parameter. More specifically,

f2(x) = (c: Context) => f(x, c)

For example, consider the following implementation of an investment calculator: InvestmentCalculator.scala.

In this example InvestmentProfile plays the role of context. It contains constants specifying the annual rate of return and the number of compounding periods per year.

The calculator's value function has two parameter lists. The first one contains the explicit parameters, the second the implicits.

In the test code we define two profiles and declare that the first id the default profile:

given InvestmentProfile = profile1

The default profile doesn't need to be specified when computing payoff1.

Conversions

Scala's Conversion[F, T] class  is a contextual abstraction specifying how to convert values of type F that appear in places where values of type T are expected.