# Type Lambdas in Scala 3

This article is a bit more difficult — it’s aimed at the experienced Scala developer who can think at a higher level. Ideally, you’ve read the previous article - it serves as a prep for this one. Type lambdas are simple to express in Scala 3, but the ramifications are deep.

## 1. Background

We discussed in the previous article about categorizing types in Scala into *kinds*. Scala 3 is no different here. However, it introduces a new concept and a syntactic structure to express it, which might look daunting and hard to wrap your head around.

To quickly recap:

- Scala types belong to
*kinds*. Think of kinds as*types of types*. - Plain types like
`Int`

,`String`

or your own non-generic classes belong to the*value-level*kind — the ones you can attach to values. - Generic types like
`List`

belong to what I called the level-1 kind — they take plain (level-0) types as type arguments. - Scala allows us to express higher-kinded types — generic types whose type arguments are also generic. I called this kind the level-2 kind.
- Generic types can’t be attached to values on their own; they need the right type arguments (of inferior kinds) in place. For this reason, they’re called type constructors.

## 2. Types Look Like Functions

As I mentioned before, generic types need the appropriate type arguments before they can be attached to a value. We can never use the `List`

type directly to a value, but only `List[Int]`

(or some other concrete type).

You can therefore think of `List`

(the generic type itself) as similar to a function, which takes a level-0 type and returns a level-0 type. This “function” from level-0 types to level-0 types represents the *kind* which `List`

belongs to. In Scala 2, representing this such a type was horrible (`{ type T[A] = List[A] })#T`

, yuck). In Scala 3, it looks much more similar to a function:

```
[X] =>> List[X]
```

Read this structure as “a type that takes a type argument `X`

and results in the type `List[X]`

”. This does the exact same thing as the `List`

type (by itself): takes a type argument and results in a new type.

Some more examples in increasing order of complexity:

`[T] =>> Map[String, T]`

is a type which takes a single type argument`T`

and “returns” a`Map`

type with`String`

as key and`T`

as values`[T, E] =>> Either[Option[T], E]`

is a type which takes two type arguments and gives you back a concrete`Either`

type with`Option[T]`

and`E`

`[F[_]] =>> F[Int]`

is a type which takes a type argument which is itself generic (like`List`

) and gives you back that type, typed with`Int`

(too many types, I know)

## 3. Why We Need Type Lambdas

Type lambdas become important as we start to work with higher-kinded types. Consider Monad, one of the most popular higher-kinded type classes. In its simplest form, it looks like this:

```
trait Monad[M[_]] {
def pure[A](a: A): M[A]
def flatMap[A, B](m: M[A])(f: A => M[B]): M[B]
}
```

You might also know that `Either`

is a monadic data structure (another article on that, perhaps), so we can write a `Monad`

for it. However, `Either`

takes two type arguments, whereas `Monad`

requires that its type argument take only one. How do we write it? We would like to write something along the lines of

```
class EitherMonad[T] extends Monad[Either[T, ?]] {
// ... implementation
}
```

In this way, this `EitherMonad`

could work for both `Either[Exception, Int]`

and `Either[String, Int]`

, for example (where `Int`

is the desired type). Given an error type `E`

, we’d like `EitherMonad`

to work with `Either[E, Int]`

whatever concrete `E`

we might end up using.

Sadly, the above structure is not valid Scala.

The answer is that we would write something like

```
scala 3
class EitherMonad[T] extends Monad[[E] =>> Either[T, E]] {
// ... implementation
}
```

It’s as if we had a two-argument function, and we needed to pass a partial application of it to another function.

If this is really abstract and hard to wrap your head around, I feel ya.

Prior to Scala 3, libraries like Cats used to resort to compiler plugins (kind-projector) to achieve something akin to the `?`

structure above. Now in Scala 3, it’s expressly permitted in the language.

## 4. Conclusion

With a simple syntactic structure, Scala 3 solved a problem that API designers had been facing (and bending over backwards) for ages - how to define higher-kinded types where some type arguments are left “blank”.

In a future article, we’ll talk about some more advanced capabilities (and pitfalls) of type lambdas.