Skip to content

Commit 330f2d6

Browse files
committed
Rename is to forms
This is a trial balloon to see whether `forms` works better than `this`. My immediate reaction is meh. Sometimes it's OK, at other times I liked `is` better. But I admit there's bias since the examples were chosen to work well with `is`.
1 parent f074b39 commit 330f2d6

18 files changed

+72
-72
lines changed

docs/_docs/reference/experimental/typeclasses.md

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -134,11 +134,11 @@ We introduce a standard type alias `is` in the Scala package or in `Predef`, def
134134
This makes writing instance definitions quite pleasant. Examples:
135135

136136
```scala
137-
given Int is Ord ...
138-
given Int is Monoid ...
137+
given Int forms Ord ...
138+
given Int forms Monoid ...
139139

140140
type Reader = [X] =>> Env => X
141-
given Reader is Monad ...
141+
given Reader forms Monad ...
142142
```
143143

144144
(more examples will follow below)
@@ -149,7 +149,7 @@ This makes writing instance definitions quite pleasant. Examples:
149149

150150
Context bounds are a convenient and legible abbreviation. A problem so far is that they are always anonymous, one cannot name the using parameter to which a context bound expands. For instance, without the trick of defining a universal "trampoline" `unit` in the `Monoid` companion object, we would have to write `reduce` like this:
151151
```scala
152-
def reduce[A](xs: List[A])(using m: A is Monoid) =
152+
def reduce[A](xs: List[A])(using m: A forms Monoid) =
153153
xs.foldLeft(m.unit)(_ `combine` _)
154154
```
155155

@@ -197,7 +197,7 @@ Context bounds are currently translated to implicit parameters in the last param
197197
```
198198
With the current translation, this would give
199199
```scala
200-
def f[C](x: C.input)(using C: C is ParserCombinator)
200+
def f[C](x: C.input)(using C: C forms ParserCombinator)
201201
```
202202
But this is ill-typed, since the `C` in `C.input` refers to the `C` introduced in the using clause, which comes later.
203203

@@ -254,7 +254,7 @@ type T: C
254254
in a trait will then expand to
255255
```scala
256256
type T
257-
given T is C = deferred
257+
given T forms C = deferred
258258
```
259259

260260

@@ -281,14 +281,14 @@ The awkwardness of the given syntax was forced upon us since we insisted that gi
281281
and we can use a more intuitive syntax for givens like this:
282282

283283
```scala
284-
given Int is Ord:
284+
given Int forms Ord:
285285
def compare(x: A, y: A) = ...
286286

287-
given [A: Ord] => List[A] is Ord:
287+
given [A: Ord] => List[A] forms Ord:
288288
def compare(x: A, y: A) =
289289
...
290290

291-
given Int is Monoid as intMonoid:
291+
given Int forms Monoid as intMonoid:
292292
extension (x: Int) def combine(y: Int) = x + y
293293
def unit = 0
294294
```
@@ -303,7 +303,7 @@ The underlying principles are:
303303
- an implementation which consists of either an `=` and an expression,
304304
or a template body.
305305

306-
- We get the pleasing `<instance-type> is <type-class>` syntax simply by using the predefined infix type `is`.
306+
- We get the pleasing `<instance-type> forms <type-class>` syntax simply by using the predefined infix type `forms`.
307307
- Since there is no more middle `:` separating name and parameters from the implemented type, we can use a `:` to start the class body without looking unnatural. That eliminates the special case where `with` was used before.
308308

309309
This will be a fairly significant change to the given syntax. I believe there's still a possibility to do this,
@@ -326,7 +326,7 @@ This is less of a disruption than it might appear at first:
326326
- `given T` was illegal before since abstract givens could not be anonymous.
327327
It now means a concrete given of class `T` with no member definitions. This
328328
is the natural interpretation for simple tagging given clauses such as
329-
`given String is Value`.
329+
`given String forms Value`.
330330
- `given x: T` is legacy syntax for a deferred given.
331331
- `given T as x = deferred` is the analogous new syntax, which is more powerful since
332332
it allows for automatic instantiation.
@@ -396,14 +396,14 @@ Here are some standard type classes, which were mostly already introduced at the
396396

397397
// Instances
398398

399-
given Int is Ord:
399+
given Int forms Ord:
400400
extension (x: Int)
401401
def compareTo(y: Int) =
402402
if x < y then -1
403403
else if x > y then +1
404404
else 0
405405

406-
given [T: Ord] => List[T] is Ord:
406+
given [T: Ord] => List[T] forms Ord:
407407
extension (xs: List[T]) def compareTo(ys: List[T]): Int =
408408
(xs, ys) match
409409
case (Nil, Nil) => 0
@@ -413,7 +413,7 @@ Here are some standard type classes, which were mostly already introduced at the
413413
val fst = x.compareTo(y)
414414
if (fst != 0) fst else xs1.compareTo(ys1)
415415

416-
given List is Monad:
416+
given List forms Monad:
417417
extension [A](xs: List[A])
418418
def flatMap[B](f: A => List[B]): List[B] =
419419
xs.flatMap(f)
@@ -422,7 +422,7 @@ Here are some standard type classes, which were mostly already introduced at the
422422

423423
type Reader[Ctx] = [X] =>> Ctx => X
424424

425-
given [Ctx] => Reader[Ctx] is Monad:
425+
given [Ctx] => Reader[Ctx] forms Monad:
426426
extension [A](r: Ctx => A)
427427
def flatMap[B](f: A => Ctx => B): Ctx => B =
428428
ctx => f(r(ctx))(ctx)
@@ -443,7 +443,7 @@ Here are some standard type classes, which were mostly already introduced at the
443443
def maximum[T: Ord](xs: List[T]): T =
444444
xs.reduce(_ `max` _)
445445

446-
given [T: Ord] => T is Ord as descending:
446+
given [T: Ord] => T forms Ord as descending:
447447
extension (x: T) def compareTo(y: T) = T.compareTo(y)(x)
448448

449449
def minimum[T: Ord](xs: List[T]) =
@@ -483,11 +483,11 @@ trait TupleOf[+A]:
483483

484484
object TupleOf:
485485

486-
given EmptyTuple is TupleOf[Nothing]:
486+
given EmptyTuple forms TupleOf[Nothing]:
487487
type Mapped[+A] = EmptyTuple
488488
def map[B](x: EmptyTuple)(f: Nothing => B): Mapped[B] = x
489489

490-
given [A, Rest <: Tuple : TupleOf[A]] => A *: Rest is TupleOf[A]:
490+
given [A, Rest <: Tuple : TupleOf[A]] => A *: Rest forms TupleOf[A]:
491491
type Mapped[+A] = A *: Rest.Mapped[A]
492492
def map[B](x: A *: Rest)(f: A => B): Mapped[B] =
493493
f(x.head) *: Rest.map(x.tail)(f)
@@ -532,14 +532,14 @@ end Combinator
532532
case class Apply[I, R](action: I => Option[R])
533533
case class Combine[A, B](a: A, b: B)
534534

535-
given [I, R] => Apply[I, R] is Combinator:
535+
given [I, R] => Apply[I, R] forms Combinator:
536536
type Input = I
537537
type Result = R
538538
extension (self: Apply[I, R])
539539
def parse(in: I): Option[R] = self.action(in)
540540

541541
given [A: Combinator, B: Combinator { type Input = A.Input }]
542-
=> Combine[A, B] is Combinator:
542+
=> Combine[A, B] forms Combinator:
543543
type Input = A.Input
544544
type Result = (A.Result, B.Result)
545545
extension (self: Combine[A, B])
@@ -567,7 +567,7 @@ to take the original example and show how it can be made to work with the new co
567567
_Note 2:_ One could improve the notation even further by adding equality constraints in the style of Swift, which in turn resemble the _sharing constraints_ of SML. A hypothetical syntax applied to the second given would be:
568568
```scala
569569
given [A: Combinator, B: Combinator with A.Input == B.Input]
570-
=> Combine[A, B] is Combinator:
570+
=> Combine[A, B] forms Combinator:
571571
```
572572
This variant is aesthetically pleasing since it makes the equality constraint symmetric. The original version had to use an asymmetric refinement on the second type parameter bound instead. For now, such constraints are neither implemented nor proposed. This is left as a possibility for future work. Note also the analogy with
573573
the work of @mbovel and @Sporarum on refinement types, where similar `with` clauses can appear for term parameters. If that work goes ahead, we could possibly revisit the issue of `with` clauses also for type parameters.

library/src/scala/runtime/stdLibPatches/Predef.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,6 @@ object Predef:
7171
*
7272
* which is what is needed for a context bound `[A: TC]`.
7373
*/
74-
infix type is[A <: AnyKind, B <: {type Self <: AnyKind}] = B { type Self = A }
74+
infix type forms[A <: AnyKind, B <: {type Self <: AnyKind}] = B { type Self = A }
7575

7676
end Predef

tests/pos/FromString.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ trait FromString:
44
type Self
55
def fromString(s: String): Self
66

7-
given Int is FromString = _.toInt
7+
given Int forms FromString = _.toInt
88

9-
given Double is FromString = _.toDouble
9+
given Double forms FromString = _.toDouble
1010

1111
def add[N: {FromString, Numeric as num}](a: String, b: String): N =
1212
num.plus(N.fromString(a), N.fromString(b))

tests/pos/deferredSummon.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ trait Ord:
55

66
trait A:
77
type Elem
8-
given Elem is Ord = deferred
9-
def foo = summon[Elem is Ord]
8+
given Elem forms Ord = deferred
9+
def foo = summon[Elem forms Ord]
1010

1111
trait B:
1212
type Elem: Ord
13-
def foo = summon[Elem is Ord]
13+
def foo = summon[Elem forms Ord]
1414

1515
object Inst:
16-
given Int is Ord:
16+
given Int forms Ord:
1717
def less(x: Int, y: Int) = x < y
1818

1919
object Test1:

tests/pos/hylolib-extract.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ trait Collection:
1414

1515
class BitArray
1616

17-
given Boolean is Value:
17+
given Boolean forms Value:
1818
extension (self: Self) def eq(other: Self): Boolean =
1919
self == other
2020

21-
given BitArray is Collection:
21+
given BitArray forms Collection:
2222
type Element = Boolean
2323

2424
extension [Self: Value](self: Self)

tests/pos/hylolib/AnyCollection.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ object AnyCollection {
3838

3939
}
4040

41-
given [T: Value] => AnyCollection[T] is Collection:
41+
given [T: Value] => AnyCollection[T] forms Collection:
4242

4343
type Element = T
4444
type Position = AnyValue

tests/pos/hylolib/AnyValue.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ object AnyValue {
5858

5959
}
6060

61-
given AnyValue is Value:
61+
given AnyValue forms Value:
6262

6363
extension (self: AnyValue)
6464
def copy(): AnyValue = self.copy()

tests/pos/hylolib/BitArray.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ object BitArray {
318318

319319
}
320320

321-
given BitArray.Position is Value:
321+
given BitArray.Position forms Value:
322322

323323
extension (self: BitArray.Position)
324324

@@ -331,7 +331,7 @@ given BitArray.Position is Value:
331331
def hashInto(hasher: Hasher): Hasher =
332332
self.hashInto(hasher)
333333

334-
given BitArray is Collection:
334+
given BitArray forms Collection:
335335

336336
type Element = Boolean
337337
type Position = BitArray.Position
@@ -353,7 +353,7 @@ given BitArray is Collection:
353353
def at(p: BitArray.Position): Boolean =
354354
self.at(p)
355355

356-
given BitArray is StringConvertible:
356+
given BitArray forms StringConvertible:
357357
extension (self: BitArray)
358358
override def description: String =
359359
var contents = mutable.StringBuilder()

tests/pos/hylolib/HyArray.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ object HyArray {
158158

159159
}
160160

161-
given [T: Value] => HyArray[T] is Value:
161+
given [T: Value] => HyArray[T] forms Value:
162162

163163
extension (self: HyArray[T])
164164

@@ -171,7 +171,7 @@ given [T: Value] => HyArray[T] is Value:
171171
def hashInto(hasher: Hasher): Hasher =
172172
self.reduce(hasher)((h, e) => e.hashInto(h))
173173

174-
given [T: Value] => HyArray[T] is Collection:
174+
given [T: Value] => HyArray[T] forms Collection:
175175

176176
type Element = T
177177
type Position = Int
@@ -192,7 +192,7 @@ given [T: Value] => HyArray[T] is Collection:
192192

193193
def at(p: Int) = self.at(p)
194194

195-
given [T: {Value, StringConvertible}] => HyArray[T] is StringConvertible:
195+
given [T: {Value, StringConvertible}] => HyArray[T] forms StringConvertible:
196196
extension (self: HyArray[T])
197197
override def description: String =
198198
val contents = mutable.StringBuilder()

tests/pos/hylolib/Integers.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package hylo
22

3-
given Boolean is Value:
3+
given Boolean forms Value:
44

55
extension (self: Boolean)
66

@@ -14,7 +14,7 @@ given Boolean is Value:
1414
def hashInto(hasher: Hasher): Hasher =
1515
hasher.combine(if self then 1 else 0)
1616

17-
given Int is Value:
17+
given Int forms Value:
1818

1919
extension (self: Int)
2020

@@ -28,7 +28,7 @@ given Int is Value:
2828
def hashInto(hasher: Hasher): Hasher =
2929
hasher.combine(self)
3030

31-
given Int is Comparable:
31+
given Int forms Comparable:
3232

3333
extension (self: Int)
3434

@@ -43,4 +43,4 @@ given Int is Comparable:
4343

4444
def lt(other: Int): Boolean = self < other
4545

46-
given Int is StringConvertible
46+
given Int forms StringConvertible

0 commit comments

Comments
 (0)