# Implicit Function Types

Implicit functions are functions with (only) implicit parameters. Their types are implicit function types. Here is an example of an implicit function type:

``````type Executable[T] = (given ExecutionContext) => T
``````

An implicit function is applied to synthesized arguments, in the same way a method with a given clause is applied. For instance:

``````  given ec: ExecutionContext = ...

def f(x: Int): Executable[Int] = ...

f(2)(given ec)   // explicit argument
f(2)             // argument is inferred
``````

Conversely, if the expected type of an expression `E` is an implicit function type `(given T_1, ..., T_n) => U` and `E` is not already an implicit function literal, `E` is converted to an implicit function literal by rewriting to

``````  (given x_1: T1, ..., x_n: Tn) => E
``````

where the names `x_1`, ..., `x_n` are arbitrary. This expansion is performed before the expression `E` is typechecked, which means that `x_1`, ..., `x_n` are available as givens in `E`.

Like their types, implicit function literals are written with a `given` prefix. They differ from normal function literals in two ways:

1. Their parameters are defined with a given clause.
2. Their types are implicit function types.

For example, continuing with the previous definitions,

``````  def g(arg: Executable[Int]) = ...

g(22)      // is expanded to g((given ev) => 22)

g(f(2))    // is expanded to g((given ev) => f(2)(given ev))

g((given ctx) => f(22)(given ctx)) // is left as it is
``````

### Example: Builder Pattern

Implicit function types have considerable expressive power. For instance, here is how they can support the "builder pattern", where the aim is to construct tables like this:

``````  table {
row {
cell("top left")
cell("top right")
}
row {
cell("bottom left")
cell("bottom right")
}
}
``````

The idea is to define classes for `Table` and `Row` that allow addition of elements via `add`:

``````  class Table {
val rows = new ArrayBuffer[Row]
def add(r: Row): Unit = rows += r
override def toString = rows.mkString("Table(", ", ", ")")
}

class Row {
val cells = new ArrayBuffer[Cell]
def add(c: Cell): Unit = cells += c
override def toString = cells.mkString("Row(", ", ", ")")
}

case class Cell(elem: String)
``````

Then, the `table`, `row` and `cell` constructor methods can be defined with implicit function types as parameters to avoid the plumbing boilerplate that would otherwise be necessary.

``````  def table(init: (given Table) => Unit) = {
given t: Table
init
t
}

def row(init: (given Row) => Unit)(given t: Table) = {
given r: Row
init
}

def cell(str: String)(given r: Row) =
``````

With that setup, the table construction code above compiles and expands to:

``````  table { (given \$t: Table) =>
row { (given \$r: Row) =>
cell("top left")(given \$r)
cell("top right")(given \$r)
} (given \$t)
row { (given \$r: Row) =>
cell("bottom left")(given \$r)
cell("bottom right")(given \$r)
} (given \$t)
}
``````

### Example: Postconditions

As a larger example, here is a way to define constructs for checking arbitrary postconditions using an extension method `ensuring` so that the checked result can be referred to simply by `result`. The example combines opaque aliases, implicit function types, and extension methods to provide a zero-overhead abstraction.

``````object PostConditions {
opaque type WrappedResult[T] = T

def result[T](given r: WrappedResult[T]): T = r

def (x: T).ensuring[T](condition: (given WrappedResult[T]) => Boolean): T = {
assert(condition(given x))
x
}
}
import PostConditions.{ensuring, result}

val s = List(1, 2, 3).sum.ensuring(result == 6)
``````

Explanations: We use an implicit function type `(given WrappedResult[T]) => Boolean` as the type of the condition of `ensuring`. An argument to `ensuring` such as `(result == 6)` will therefore have a given instance of type `WrappedResult[T]` in scope to pass along to the `result` method. `WrappedResult` is a fresh type, to make sure that we do not get unwanted givens in scope (this is good practice in all cases where implicit parameters are involved). Since `WrappedResult` is an opaque type alias, its values need not be boxed, and since `ensuring` is added as an extension method, its argument does not need boxing either. Hence, the implementation of `ensuring` is as about as efficient as the best possible code one could write by hand:

``````{ val result = List(1, 2, 3).sum
assert(result == 6)
result
}
``````

### Reference

For more info, see the blog article, (which uses a different syntax that has been superseded).

More details