Skip to content

Commit 3c29212

Browse files
committed
Rename "implicit function type" to "query type"
1 parent 379bc06 commit 3c29212

File tree

5 files changed

+58
-62
lines changed

5 files changed

+58
-62
lines changed

docs/docs/reference/changed-features/eta-expansion-spec.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,13 @@ implicit val bla: Double = 1.0
4848
val bar = foo // val bar: Int => Float = ...
4949
```
5050

51-
## Automatic Eta-Expansion and implicit function types
51+
## Automatic Eta-Expansion and query types
5252

53-
Methods with implicit parameter lists can be assigned to a value with an implicit function type
54-
only by using the expected type explicitly.
53+
A method with inferable parameters can be expanded to a value of query type by writing the expected query type explicitly.
5554

5655
```scala
57-
def foo(x: Int)(implicit p: Double): Float = ???
58-
val bar: implicit Double => Float = foo(3) // val bar: implicit Double => Float = ...
56+
def foo(x: Int) given (p: Double): Float = ???
57+
val bar: given Double => Float = foo(3) // val bar: given Double => Float = ...
5958
```
6059

6160
## Rules

docs/docs/reference/instances/context-params.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
layout: doc-page
3-
title: "Inferable Parameters and Arguments"
3+
title: "Inferable Paramters"
44
---
55

66
Functional programming tends to express most dependencies as simple functions parameterization.
@@ -25,7 +25,7 @@ max(2, 3)
2525
```
2626
This is equally valid, and is completed by the compiler to the previous application.
2727

28-
## Anonymous Inferred Parameters
28+
## Anonymous Inferable Parameters
2929

3030
In many situations, the name of an inferable parameter of a method need not be
3131
mentioned explicitly at all, since it is only used in synthesized arguments for
@@ -54,7 +54,7 @@ def minimum[T](xs: List[T]) given Ord[T] =
5454
maximum(xs) given descending
5555
```
5656
The `minimum` method's right hand side passes `descending` as an explicit argument to `maximum(xs)`.
57-
But usually, explicit arguments for inferable parameters are be left out. For instance,
57+
But usually, explicit arguments for inferable parameters are left out. For instance,
5858
given `xs: List[Int]`, the following calls are all possible (and they all normalize to the last one:)
5959
```scala
6060
minimum(xs)
@@ -85,17 +85,18 @@ f("abc") given ctx
8585
(f given global)("abc") given ctx
8686
```
8787

88-
## Summmoning an Inferred Instance
88+
## Querying For Inferred Instances
8989

90-
A method `infer` in `Predef` creates an instance value for a given type. For example,
91-
the instance value for `Ord[List[Int]]` is generated by
90+
A method `infer` in `Predef` creates an inferred instance of a given type. For example,
91+
the inferred instance of `Ord[List[Int]]` is generated by
9292
```
9393
infer[Ord[List[Int]]]
9494
```
9595
The `infer` method is simply defined as the identity function with an inferable parameter.
9696
```scala
9797
def infer[T] given (x: T) = x
9898
```
99+
Functions like `infer` that have only inferable parameters are also called inference _queries_.
99100

100101
## Syntax
101102

Lines changed: 24 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
layout: doc-page
3-
title: "Implicit Function Types - More Details"
3+
title: "Query Types - More Details"
44
---
55

66
Initial implementation in (#1775)[https://github.com/lampepfl/dotty/pull/1775].
@@ -12,66 +12,61 @@ Initial implementation in (#1775)[https://github.com/lampepfl/dotty/pull/1775].
1212
Expr ::= ...
1313
| `given' FunParams `=>' Expr
1414

15-
Implicit function types associate to the right, e.g.
15+
Query types associate to the right, e.g.
1616
`given S => given T => U` is the same as `given S => (given T => U)`.
1717

1818
## Implementation
1919

20-
Implicit function types are shorthands for class types that define `apply`
21-
methods with implicit parameters. Specifically, the `N`-ary function type
20+
Query types are shorthands for class types that define `apply`
21+
methods with inferable parameters. Specifically, the `N`-ary function type
2222
`T1, ..., TN => R` is a shorthand for the class type
23-
`ImplicitFunctionN[T1 , ... , TN, R]`. Such class types are assumed to have
24-
the following definitions, for any value of `N >= 1`:
23+
`ImplicitFunctionN[T1 , ... , TN, R]`. Such class types are assumed to have the following definitions, for any value of `N >= 1`:
2524
```scala
2625
package scala
2726
trait ImplicitFunctionN[-T1 , ... , -TN, +R] {
28-
def apply with (x1: T1 , ... , xN: TN): R
27+
def apply given (x1: T1 , ... , xN: TN): R
2928
}
3029
```
31-
Implicit function types erase to normal function types, so these classes are
30+
Query types erase to normal function types, so these classes are
3231
generated on the fly for typechecking, but not realized in actual code.
3332

34-
Anonymous implicit function values `given (x1: T1, ..., xn: Tn) => e` map
35-
implicit parameters `xi` of types `Ti` to a result given by expression `e`.
36-
The scope of each implicit parameter `xi` is `e`. Implicit parameters must
37-
have pairwise distinct names.
33+
Query literals `given (x1: T1, ..., xn: Tn) => e` map
34+
inferable parameters `xi` of types `Ti` to a result given by expression `e`.
35+
The scope of each implicit parameter `xi` is `e`. The parameters must have pairwise distinct names.
3836

39-
If the expected type of the anonymous implicit function is of the form
37+
If the expected type of the query literal is of the form
4038
`scala.ImplicitFunctionN[S1, ..., Sn, R]`, the expected type of `e` is `R` and
4139
the type `Ti` of any of the parameters `xi` can be omitted, in which case `Ti
42-
= Si` is assumed. If the expected type of the anonymous implicit function is
43-
some other type, all implicit parameter types must be explicitly given, and
44-
the expected type of `e` is undefined. The type of the anonymous implicit
45-
function is `scala.ImplicitFunctionN[S1, ...,Sn, T]`, where `T` is the widened
40+
= Si` is assumed. If the expected type of the query literal is
41+
some other type, all inferable parameter types must be explicitly given, and the expected type of `e` is undefined. The type of the query literal is `scala.ImplicitFunctionN[S1, ...,Sn, T]`, where `T` is the widened
4642
type of `e`. `T` must be equivalent to a type which does not refer to any of
47-
the implicit parameters `xi`.
43+
the inferable parameters `xi`.
4844

49-
The anonymous implicit function is evaluated as the instance creation
45+
The query literal is evaluated as the instance creation
5046
expression:
5147

5248
new scala.ImplicitFunctionN[T1, ..., Tn, T] {
53-
def apply with (x1: T1, ..., xn: Tn): T = e
49+
def apply given (x1: T1, ..., xn: Tn): T = e
5450
}
5551

56-
In the case of a single untyped implicit parameter, `given (x) => e` can be
52+
In the case of a single untyped parameter, `given (x) => e` can be
5753
abbreviated to `given x => e`.
5854

59-
A implicit parameter may also be a wildcard represented by an underscore `_`. In
55+
An inferable parameter may also be a wildcard represented by an underscore `_`. In
6056
that case, a fresh name for the parameter is chosen arbitrarily.
6157

6258
Note: The closing paragraph of the [Anonymous Functions section](https://www
6359
.scala-lang.org/files/archive/spec/2.12/06-expressions.html#anonymous-
64-
functions) of the Scala 2.12 is subsumed by implicit function types and should
60+
functions) of the Scala 2.12 is subsumed by query types and should
6561
be removed.
6662

67-
Anonymous implicit functions `given (x1: T1, ..., xn: Tn) => e` are
68-
automatically inserted around any expression `e` whose expected type is
63+
Query literals `given (x1: T1, ..., xn: Tn) => e` are
64+
automatically created for any expression `e` whose expected type is
6965
`scala.ImplicitFunctionN[T1, ..., Tn, R]`, unless `e` is
70-
itself a function literal. This is analogous to the automatic
66+
itself a query literal. This is analogous to the automatic
7167
insertion of `scala.Function0` around expressions in by-name argument position.
7268

73-
Implicit functions generalize to `N > 22` in the same way that functions do,
74-
see [the corresponding
69+
Query types generalize to `N > 22` in the same way that function types do, see [the corresponding
7570
documentation](https://dotty.epfl.ch/docs/reference/dropped-features/limit22.html).
7671

7772
## Examples
@@ -84,5 +79,4 @@ Gist](https://gist.github.com/OlivierBlanvillain/234d3927fe9e9c6fba074b53a7bd9
8479

8580
### Type Checking
8681

87-
After desugaring no additional typing rules are required for implicit function
88-
types.
82+
After desugaring no additional typing rules are required for query types.

docs/docs/reference/instances/implicit-function-types.md

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
---
22
layout: doc-page
3-
title: "Implicit Function Types and Values"
3+
title: "First Class Queries"
44
---
55

6-
An implicit function type describes functions with inferred parameters. Example:
6+
In the context of inference, _queries_ are functions with inferable parameters.
7+
_Query types_ are the types of first-class queries. Example:
78
```scala
89
type Contextual[T] = given Context => T
910
```
10-
A value of implicit function type is applied to inferred arguments, in
11-
the same way a method with inferred parameters is applied. For instance:
11+
A value of query type is applied to inferred arguments, in
12+
the same way a method with inferable parameters is applied. For instance:
1213
```scala
1314
inferred ctx for Context = ...
1415

@@ -17,18 +18,20 @@ the same way a method with inferred parameters is applied. For instance:
1718
f(2) given ctx // explicit argument
1819
f(2) // argument is inferred
1920
```
20-
Conversely, if the expected type of an expression `E` is an implicit
21-
function type `given (T_1, ..., T_n) => U` and `E` is not already an
22-
implicit function value, `E` is converted to an inferred function value
23-
by rewriting to
21+
Conversely, if the expected type of an expression `E` is a query
22+
type `given (T_1, ..., T_n) => U` and `E` is not already a
23+
query literal, `E` is converted to a query literal by rewriting to
2424
```scala
2525
given (x_1: T1, ..., x_n: Tn) => E
2626
```
27-
where the names `x_1`, ..., `x_n` are arbitrary. Inferred function values are written
28-
with a `given` prefix. They differ from normal function values in two ways:
27+
where the names `x_1`, ..., `x_n` are arbitrary. This expansion is performed
28+
before the expression `E` is typechecked, which means that x_1`, ..., `x_n`
29+
are available as inferred instances in `E`.
2930

30-
1. Their parameters are inferred parameters
31-
2. Their types are implicit function types.
31+
Like query types, query literals are written with a `given` prefix. They differ from normal function literals in two ways:
32+
33+
1. Their parameters are inferable.
34+
2. Their types are query types.
3235

3336
For example, continuing with the previous definitions,
3437
```scala
@@ -42,7 +45,7 @@ For example, continuing with the previous definitions,
4245
```
4346
### Example: Builder Pattern
4447

45-
Implicit function types have considerable expressive power. For
48+
Query types have considerable expressive power. For
4649
instance, here is how they can support the "builder pattern", where
4750
the aim is to construct tables like this:
4851
```scala
@@ -75,17 +78,17 @@ addition of elements via `add`:
7578
case class Cell(elem: String)
7679
```
7780
Then, the `table`, `row` and `cell` constructor methods can be defined
78-
in terms of implicit function types to avoid the plumbing boilerplate
81+
in terms of query types to avoid the plumbing boilerplate
7982
that would otherwise be necessary.
8083
```scala
8184
def table(init: given Table => Unit) = {
82-
instance t of Table
85+
inferred t for Table
8386
init
8487
t
8588
}
8689

8790
def row(init: given Row => Unit) given (t: Table) = {
88-
instance r of Row
91+
inferred r for Row
8992
init
9093
t.add(r)
9194
}
@@ -108,7 +111,7 @@ With that setup, the table construction code above compiles and expands to:
108111
```
109112
### Example: Postconditions
110113

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

113116
```scala
114117
object PostConditions {
@@ -133,10 +136,9 @@ object Test {
133136
val s = List(1, 2, 3).sum.ensuring(result == 6)
134137
}
135138
```
136-
**Explanations**: We use an implicit function type `given WrappedResult[T] => Boolean`
139+
**Explanations**: We use a query type `given WrappedResult[T] => Boolean`
137140
as the type of the condition of `ensuring`. An argument to `ensuring` such as
138-
`(result == 6)` will therefore have an implicit value of type `WrappedResult[T]` in scope
139-
to pass along to the `result` method. `WrappedResult` is a fresh type, to make sure that we do not get unwanted inferred instances in scope (this is good practice in all cases where inferred 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:
141+
`(result == 6)` will therefore have an inferred 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 inferred instances in scope (this is good practice in all cases where inferred 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:
140142

141143
{ val result = List(1, 2, 3).sum
142144
assert(result == 6)

tests/run/tagless.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// A rewrite of Olivier Blanvillain's [adaptation](https://gist.github.com/OlivierBlanvillain/48bb5c66dbb0557da50465809564ee80)
22
// of Oleg Kislyov's [lecture notes](http://okmij.org/ftp/tagless-final/course/lecture.pdf)
33
// on tagless final interpreters.
4-
// Main win: Replace Either by an "algebraic effect" using an implicit function type.
4+
// Main win: Replace Either by an "algebraic effect" using a query type.
55
object Test extends App {
66

77
// Explicit ADT

0 commit comments

Comments
 (0)