You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A `Functor` for a type provides the ability for its values to be "mapped over", i.e. apply a function that transforms inside a value while remembering its shape. For example, to modify every element of a collection without dropping or adding elements.
87
87
We can represent all types that can be "mapped over" with `F`. It's a type constructor: the type of its values becomes concrete when provided a type argument.
88
-
Therefore we write it `F[_]`, hinting that it is a type with internal details we can inspect.
88
+
Therefore we write it `F[?]`, hinting that it is a type with internal details we can inspect.
89
89
The definition of a generic `Functor` would thus be written as:
90
90
91
91
```scala
92
-
traitFunctor[F[_]] {
92
+
traitFunctor[F[?]] {
93
93
defmap[A, B](original: F[A], mapper: A=>B):F[B]
94
94
}
95
95
```
96
96
97
-
Which could read as follows: "A `Functor` for the type constructor `F[_]` represents the ability to transform `F[A]` to `F[B]` through the application of the `mapper` function whose type is `A => B`". We call the `Functor` definition here a _typeclass_.
97
+
Which could read as follows: "A `Functor` for the type constructor `F[?]` represents the ability to transform `F[A]` to `F[B]` through the application of the `mapper` function whose type is `A => B`". We call the `Functor` definition here a _typeclass_.
98
98
This way, we could define an instance of `Functor` for the `List` type:
99
99
100
100
```scala
@@ -108,7 +108,7 @@ With this `given` instance in scope, everywhere a `Functor` is expected, the com
108
108
109
109
For instance, we may write such a testing method:
110
110
```scala
111
-
defassertTransformation[F[_]:Functor, A, B](expected: F[B], original: F[A], mapping: A=>B):Unit=
111
+
defassertTransformation[F[?]:Functor, A, B](expected: F[B], original: F[A], mapping: A=>B):Unit=
@@ -122,7 +122,7 @@ That's a first step, but in practice we probably would like the `map` function t
122
122
As in the previous example of Monoids, [`extension` methods](extension-methods-new.html) help achieving that. Let's re-define the `Functor`_typeclass_ with extension methods.
123
123
124
124
```scala
125
-
traitFunctor[F[_]] {
125
+
traitFunctor[F[?]] {
126
126
def [A, B](original: F[A]).map(mapper: A=>B):F[B]
127
127
}
128
128
```
@@ -139,7 +139,7 @@ given Functor[List] {
139
139
It simplifies the `assertTransformation` method:
140
140
141
141
```scala
142
-
defassertTransformation[F[_]:Functor, A, B](expected: F[B], original: F[A], mapping: A=>B):Unit=
142
+
defassertTransformation[F[?]:Functor, A, B](expected: F[B], original: F[A], mapping: A=>B):Unit=
143
143
assert(expected == original.map(mapping))
144
144
```
145
145
@@ -156,14 +156,14 @@ Now, applying the `List.map` ability with the following mapping function as para
156
156
157
157
To avoid avoid managing lists of lists, we may want to "flatten" the values in a single list.
158
158
159
-
That's where `Monad` enters the party. A `Monad` for type `F[_]` is a `Functor[F]` with 2 more abilities:
159
+
That's where `Monad` enters the party. A `Monad` for type `F[?]` is a `Functor[F]` with 2 more abilities:
160
160
* the flatten ability we just described: turning `F[A]` to `F[B]` when given a `mapping: A => F[B]` function
161
161
* the ability to create `F[A]` from a single value `A`
162
162
163
163
Here is the translation of this definition in Scala 3:
164
164
165
165
```scala
166
-
traitMonad[F[_]] extendsFunctor[F] { // "A `Monad` for type `F[_]` is a `Functor[F]`" => thus has the `map` ability
166
+
traitMonad[F[?]] extendsFunctor[F] { // "A `Monad` for type `F[?]` is a `Functor[F]`" => thus has the `map` ability
167
167
defpure[A](x: A):F[A] // `pure` can construct F[A] from a single value A
168
168
def [A, B](x: F[A]).flatMap(f: A=>F[B]):F[B] // the flattening ability is named `flatMap`, using extension methods as previous examples
169
169
def [A, B](x: F[A]).map(f: A=>B) = x.flatMap(f `andThen` pure) // the `map(f)` ability is simply a combination of applying `f` then turning the result into an `F[A]` then applying `flatMap` to it
0 commit comments