Note: This section keeps on growing! Keep an eye on it from time to time.

A datatype is a class that encapsulates one reusable coding pattern. These solutions have a canonical implementation that is generalised for all possible uses.

Some common patterns expressed as datatypes are absence handling with `Option`

,
branching in code with `Either`

,
catching exceptions with `Try`

,
or interacting with the platform the program runs in using `IO`

.

You can read more about all the datatypes that Arrow provides in its section of the docs.

A typeclass is a specification for one behavior associated with a single type. This behavior is checked by a test suite called the “laws” for that typeclass. These test suites are available in the package arrow-tests.

What differentiates typeclasses from regular OOP inheritance is that typeclasses are meant to be implemented outside of their types. The association is done using generic parametrization rather than the usual subclassing by implementing the interface. This means that they can be implemented for any class, even those not in the current project, and allows us to make available at the global scope any one implementation of a typeclasses for the single unique type they’re associated with.

Examples of these behaviors are comparability (`Eq`

),
composability (`Monoid`

),
its contents can be mapped from one type to another (`Functor`

),
or error recovery (`MonadError`

).

You can read more about all the typeclasses that Arrow provides in its section of the docs.

To define a fully featured typeclass in Λrrow you use an interface that extends from `TC`

, and use the annotation `@typeclass`

to generate all boilerplate related to global lookup, which is explained below.
The annotation and interface to extend have different names to avoid collision.

```
@typeclass
interface Eq<F>: TC {
fun eqv(a: F, b: F): Boolean
}
```

A single implementation of a typeclass for a specific datatype or class. Because typeclasses require generic parameters each implementation is meant to be unique for that parameter.

```
@instance
interface IntEqInstance: Eq<Int> {
override fun eqv(a: Int, b: Int): Boolean = a == b
}
```

In Λrrow all typeclass instances can be looked up in a global scope using an inlined reified method with the same name as the typeclass. Its generic parameter will be used for the lookup, which reinforces the concept that most typeclasses should have a single implementation per type.

All the instances in the library are already registered and available in the global scope.
If you’re defining your own instances and would like for them to be discoverable in the global scope
you can add them by annotating them as `@instance`

, and Λrrow’s annotation processor will register them for you. The interface has to have all required methods defined by default implementations, and be named after the datatype + typeclass + the word `Instance`

.

```
import arrow.*
import arrow.typeclasses.*
eq<Int>()
// arrow.instances.IntEqInstance@31fe20d0
```

NOTE: This approach to type constructors will be simplified if KEEP-87 is approved. Go vote!

A type constructor is any class or interface that has at least one generic parameter. For example,
`ListK<A>`

or `Option<A>`

.
They’re called constructors because they’re similar to a factory function where the parameter is `A`

, except type constructors work only for types.
So, we could say that after applying the parameter `Int`

to the type constructor `ListK<A>`

it returns a `ListK<Int>`

.
As `ListK<Int>`

isn’t parametrized in any generic value it is not considered a type constructor anymore, just a regular type.

Like functions, a type constructor with several parameters like `Either<L, R>`

can be partially applied for one of them to return another type constructor with one fewer parameter,
for example applying `Throwable`

to the left side yields `Either<Throwable, A>`

, or applying `String`

to the right side results in `Either<E, String>`

.

Type constructors are useful when matched with typeclasses because they help us represent instances of parametrized classes -the containers- that work for all generic parameters -the content-.
As type constructors is not a first class feature in Kotlin, Λrrow uses an interface `Kind<F, A>`

to represent them.
Kind stands for Higher Kind, which is the name of the language feature that allows working directly with type constructors.

In a Higher Kind with the shape `Kind<F, A>`

, if `A`

is the type of the content then `F`

has to be the type of the container.

A malformed Higher Kind would use the whole type constructor to define the container, duplicating the type of the content .
This incorrect representation has large a number of issues when working with partially applied types and nested types.`Kind<Option<A>, A>`

What Λrrow does instead is define a surrogate type that’s not parametrized to represent `F`

.
These types are named same as the container and prefixed by For, as in `ForOption`

or `ForListK`

.

```
class ForOption private constructor()
sealed class Option<A>: Kind<ForOption, A>
```

```
class ForListK private constructor()
data class ListK<A>(val list: List<A>): Kind<ForListK, A>
```

As `ListK<A>`

is the only existing implementation of `Kind<ForListK, A>`

, we can define an extension function on `Kind<ForListK, A>`

to do the downcasting safely for us.
This function by convention is called `fix()`

, as in, fixing a type from something generic into concrete.

```
fun Kind<ForListK, A>.fix() = this as ListK<A>
```

This way we have can to convert from `ListK<A>`

to `Kind<ForListK, A>`

via simple subclassing and from `Kind<ForListK, A>`

to `ListK<A>`

using the function `fix()`

.
Being able to define extension functions that work for partially applied generics is a feature from Kotlin that’s not available in Java.
You can define `fun Kind<ForOption, A>.fix()`

and `fun Kind<ForListK, A>.fix()`

and the compiler can smartly decide which one you’re trying to use.
If it can’t it means there’s an ambiguity you should fix!

The function `fix()`

is already defined for all datatypes in Λrrow, alongside a typealias for its `Kind<F, A>`

specialization done by suffixing the type with Of, as in `ListKOf<A>`

or `OptionOf<A>`

. If you’re creating your own datatype that’s also a type constructor and would like to create all these helper types and functions,
you can do so simply by annotating it as `@higerkind`

and the Λrrow’s annotation processor will create them for you.

```
@higherkind
data class ListK<A>(val list: List<A>): ListKOf<A>
// Generates the following code:
//
// class ForListK private constructor()
// typealias ListKOf<A> = Kind<ForListK, A>
// fun ListKOf<A>.fix() = this as ListK<A>
```

Note that the annotation `@higerkind`

will also generate the integration typealiases required by KindedJ as long as the datatype is invariant. You can read more about sharing Higher Kinds and type constructors across JVM libraries in KindedJ’s README.

Now that we have a way of representing generic constructors for any type, we can write typeclasses that are parametrised for containers.

Let’s take as an example a typeclass that specifies how to map the contents of any container `F`

. This typeclass that comes from computer science is called a `Functor`

.

```
@typeclass
interface Functor<F>: TC {
fun <A, B> map(fa: Kind<F, A>, f: (A) -> B): Kind<F, B>
}
```

See how the class is parametrized on the container `F`

, and the function is parametrized to the content `A`

. This way we can have a single representation that works for all mappings from `A`

to `B`

.

Let’s define an instance of `Functor`

for the datatype `ListK`

, our own wrapper for lists.

```
@instance
interface ListKFunctorInstance : Functor<ForListK> {
override fun <A, B> map(fa: Kind<ForListK, A>, f: (A) -> B): ListK<B> {
val list: ListK<A> = fa.fix()
return list.map(f)
}
}
```

This interface extends `Functor`

for the value `F`

of `ListK`

. We use an annotation processor `@instance`

to generate an object out of an interface with all the default methods already defined, and to add that method to the global typeclass instance lookup. See that we respect the naming convention of datatype + typeclass + the word `Instance`

.

```
@instance
interface ListKFunctorInstance : Functor<ForListK>
```

The signature of `map`

once the types have been replaced takes a parameter `Kind<ForListK, A>`

, which is the receiver, and a mapping function from `A`

to `B`

. This means that map will work for all instances of `ListK<A>`

for whatever the value of `A`

can be.

```
override fun <A, B> map(fa: Kind<ForListK, A>, f: (A) -> B): ListK<B>
```

The implementation is short. On the first line we downcast `Kind<ForListK, A>`

to `ListK<A>`

using `fix()`

. Once the value has been downcasted, the implementation of map inside the `ListK<A>`

we have obtained already implements the expected behavior of map.

```
val list: ListK<A> = fa.fix()
return list.map(f)
```

Higher kinds are also used to model functions that require for a datatype to implement a typeclass. This way you can create functions that abstract behavior (defined by a typeclass) and allow callers to define which datatype they’d like to apply it to.

Let’s use the typeclass `Applicative`

, that contains the constructor function `pure()`

.

```
@typeclass
interface Applicative<F>: Functor<F>, TC {
// Constructs the current datatype with a value of type A inside
fun <A> pure(a: A): Kind<F, A>
/* ... */
}
```

Once we have this typeclass behavior define we can now write a function that’s parametrized for any `F`

that has one instance of `Applicative`

. The function uses the constructor `pure`

to create a value of type `Kind<F, User>`

, effectively generifying the return on any container `F`

.

```
inline fun <reified F> randomUserStructure(f: (Int) -> User, AP: Applicative<F> = applicative<F>()): Kind<F, User> =
AP.pure(f(Math.random()))
```

Now lets create a simple example instance of `Applicative`

where our `F`

is `ListK`

. This implementation of a `pure`

constructor is trivial for lists, as it just requires wrapping the value.

```
@instance
interface ListKApplicativeInstance : Applicative<ForListK> {
override fun <A> pure(a: A): Kind<ForListK, A> = ListK(listOf(a))
/* ... */
}
```

And now we can show how this function `randomUserStructure()`

can be used for any datatype that implements `Applicative`

. As the function returns a value `Kind<F, User>`

the caller is responsible of calling `fix()`

to downcast it to the expected value.

```
val list = randomUserStructure(::User, ListK.applicative()).fix()
//[User(342)]
```

```
val option = randomUserStructure(::User, Option.applicative()).fix()
//Some(User(765))
```

```
val either = randomUserStructure(::User, Either.applicative<Unit>()).fix()
//Right(User(221))
```

Passing the instance in every function call seems like a burden. But, remember that all instances already defined in Λrrow can be looked up globally!! That means that whenever asking for any instance you can ask for a default value that’ll be looked up globally based on its type:

```
import arrow.data.*
applicative<ForListK>()
// arrow.data.ListKApplicativeInstanceImplicits$instance$1@7f1b488c
```

```
import arrow.core.*
applicative<ForOption>()
// arrow.core.OptionApplicativeInstanceImplicits$instance$1@69e34852
```

So, because `randomUserStructure`

provides a default value for `Applicative`

that’s looked up globally, we can call it without passing the second parameter as long as we tell the compiler what type we’re expecting the function to return.

```
val list: ListK<User> = randomUserStructure(::User).fix()
//[User(342)]
```

```
val option: Option<User> = randomUserStructure(::User).fix()
//Some(User(765))
```

This system of looking up global instances and allowing manual overrides has several pitfalls and can and will be simplified when the feature request KEEP-87 is implemented into the language.