Skip to content

Commit a516cf6

Browse files
committed
Fix typos
1 parent 1f10973 commit a516cf6

File tree

1 file changed

+10
-10
lines changed

1 file changed

+10
-10
lines changed

docs/_docs/reference/experimental/typeclasses.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ A type class in Scala is a pattern where we define
1515
- given instances at specific instantiations of that trait,
1616
- using clauses or context bounds abstracting over that trait.
1717

18-
Type classes as a pattern work overall OK, but if we compare them to native implementations in Haskell, or protocols in Swift, or traits in Rust, then there are some idiosyncracies and rough corners which in the end make them
18+
Type classes as a pattern work overall OK, but if we compare them to native implementations in Haskell, or protocols in Swift, or traits in Rust, then there are some idiosyncrasies and rough corners which in the end make them
1919
a bit cumbersome and limiting for standard generic programming patterns. Much has improved since Scala 2's implicits, but there is still some gap to bridge to get to parity with these languages.
2020

2121
This note shows that with some fairly small and reasonable tweaks to Scala's syntax and typing rules we can obtain a much better scheme for working with type classes, or do generic programming in general.
@@ -67,7 +67,7 @@ requires that `Ordering` is a trait or class with a single type parameter (which
6767
def flatMap[B](f: A => Self[B]): Self[B]
6868
def map[B](f: A => B) = x.flatMap(f `andThen` pure)
6969

70-
def reduce[A: Monoid](xs: List[A] =
70+
def reduce[A: Monoid](xs: List[A]): A =
7171
xs.foldLeft(Monoid.unit)(_ `combine` _)
7272

7373
trait ParserCombinator:
@@ -86,7 +86,7 @@ requires that `Ordering` is a trait or class with a single type parameter (which
8686
- Gives a clear indication of traits intended as type classes. A trait is a type class
8787
if it has type `Self` as a member
8888
- Allows to create aggregate type classes that combine givens via intersection types.
89-
- Allows to use refinements in context bounds (the `combine` example above would be very awkward to express using the old way of context bounds expanding to type copnstructors).
89+
- Allows to use refinements in context bounds (the `combine` example above would be very awkward to express using the old way of context bounds expanding to type constructors).
9090

9191
`Self`-based context bounds are a better fit for a dependently typed language like Scala than parameter-based ones. The main reason is that we are dealing with proper types, not type constructors. Proper types can be parameterized, intersected, or refined. This makes `Self`-based designs inherently more compositional than parameterized ones.
9292

@@ -120,7 +120,7 @@ and not to:
120120

121121
Why not use `This` for the self type? The name `This` suggests that it is the type of `this`. But this is not true for type class traits. `Self` is the name of the type implementing a distinguished _member type_ of the trait in a `given` definition. `Self` is an established term in both Rust and Swift with the meaning used here.
122122

123-
One possible objection to the `Self` based design is that it does not cover "multi-parameter" type classes. But neither do context bounds! "Multi-parameter" type classes in Scala are simply givens that can be synthesized with the standard mechanisms. Type classes in the strict sense abstract only over a single type, namely the implementatation type of a trait.
123+
One possible objection to the `Self` based design is that it does not cover "multi-parameter" type classes. But neither do context bounds! "Multi-parameter" type classes in Scala are simply givens that can be synthesized with the standard mechanisms. Type classes in the strict sense abstract only over a single type, namely the implementation type of a trait.
124124

125125

126126
## Auxiliary Type Alias `is`
@@ -383,7 +383,7 @@ Here are some standard type classes, which were mostly already introduced at the
383383
def unit: Self
384384

385385
trait Functor:
386-
type Self[A]
386+
type Self[A] // Here, Self is a type constructor with parameter A
387387
extension [A](x: Self[A]) def map[B](f: A => B): Self[B]
388388

389389
trait Monad extends Functor:
@@ -547,7 +547,7 @@ given [A: Combinator, B: Combinator { type Input = A.Input }]
547547
y <- self.b.parse(in)
548548
yield (x, y)
549549
```
550-
The example is now as expressed as straighforwardly as it should be:
550+
The example is now as expressed as straightforwardly as it should be:
551551

552552
- `Combinator` is a type class with two associated types, `Input` and `Result`, and a `parse` method.
553553
- `Apply` and `Combine` are two data constructors representing parser combinators. They are declared to be `Combinators` in the two subsequent `given` declarations.
@@ -567,12 +567,12 @@ _Note 2:_ One could improve the notation even further by adding equality constra
567567
given [A: Combinator, B: Combinator with A.Input == B.Input]
568568
=> Combine[A, B] is Combinator:
569569
```
570-
This variant is esthetically 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
570+
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
571571
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.
572572

573573
### Example 4
574574

575-
Dimi Recordon tried to [port some core elenents](https://github.com/kyouko-taiga/scala-hylolib) of the type class based [Hylo standard library to Scala](https://github.com/hylo-lang/hylo/tree/main/StandardLibrary/Sources). It worked to some degree, but there were some things that could not be expressed, and more things that could be expressed only awkwardly.
575+
Dimi Racordon tried to [port some core elements](https://github.com/kyouko-taiga/scala-hylolib) of the type class based [Hylo standard library to Scala](https://github.com/hylo-lang/hylo/tree/main/StandardLibrary/Sources). It worked to some degree, but there were some things that could not be expressed, and more things that could be expressed only awkwardly.
576576

577577
With the improvements proposed here, the library can now be expressed quite clearly and straightforwardly. See tests/pos/hylolib in this PR for details.
578578

@@ -636,7 +636,7 @@ These would replace the previous syntax using `@`:
636636

637637
val xs @ (x :: xs1) = ys.checkedCast
638638
```
639-
**Advantages:** No unpronouncible and non-standard symbol like `@`. More regularity.
639+
**Advantages:** No unpronounceable and non-standard symbol like `@`. More regularity.
640640

641641
Generally, we want to use `as name` to attach a name for some entity that could also have been used stand-alone.
642642

@@ -668,5 +668,5 @@ type classes in Haskell, or with traits in Rust, or with protocols in Swift, or
668668
The proposed scheme has similar expressiveness to Protocols in Swift or Traits in Rust. Both of these were largely influenced by Jeremy Siek's PdD thesis "[A language for generic programming](https://scholarworks.iu.edu/dspace/handle/2022/7067)", which was first proposed as a way to implement concepts in C++. C++ did not follow Siek's approach, but Swift and Rust did.
669669

670670
In Siek's thesis and in the formal treatments of Rust and Swift,
671-
type class concepts are explained by mapping them to a lower level language of explicit dictionaries with representants for terms and types. Crucially, that lower level is not expressible without loss of granularity in the source language itself, since type representants are mapped to term dictionaries. By contrast, the current proposal expands type class concepts into other well-typed Scala constructs, which ultimately map into well-typed DOT programs. Type classes are simply a convenient notation for something that can already be expressed in Scala. In that sense, we stay true to the philosophy of a _scalable language_, where a small core can support a large range of advanced use cases.
671+
type class concepts are explained by mapping them to a lower level language of explicit dictionaries with representations for terms and types. Crucially, that lower level is not expressible without loss of granularity in the source language itself, since type representations are mapped to term dictionaries. By contrast, the current proposal expands type class concepts into other well-typed Scala constructs, which ultimately map into well-typed DOT programs. Type classes are simply a convenient notation for something that can already be expressed in Scala. In that sense, we stay true to the philosophy of a _scalable language_, where a small core can support a large range of advanced use cases.
672672

0 commit comments

Comments
 (0)