First of all, if you didn't read the previous post, go do so, otherwise you might be missing some essential concepts!

**Kotlin Functors, Applicatives, And Monads in Pictures. Part 1/3 (draft)**

*Simple enough. Lets extend this by saying that any value can be in a context. For now you can think of a context as a…*medium.com

### Applicatives

Applicatives take it to the next level. With an applicative, our values are wrapped in a context, just like Functors:

But our functions are wrapped in a context too!

Yeah. Let that sink in. Applicatives don’t kid around. Unlike Haskell, Kotlin doesn’t have *yet* a built-in way to deal with Applicatives. But it is very easy to add one! We can define an `apply`

function for every type supporting Applicative, which knows how to apply a function wrapped in the context of the type to a value wrapped in the same context:

infix fun <A, B> Option<(A) -> B>.apply(f: Option<A>): Option<B> =

when (this) {

is Option.None -> Option.None

is Option.Some -> f.map(this.value)

}

infix inline fun <A, reified B> Array<(A) -> B>.apply(a: Array<A>) =

Array(this.size * a.size) {

this[it / a.size](a[it % a.size])

}

If both `this`

and the function are `Some`

, then the function is applied to the unwrapped option, otherwise `None`

is returned.

For the `Array`

I'm using its constructor parameters to generate the array, although note that this wouldn't be the most performant choice for bigger arrays.

Note:this would be the`<*>`

in Haskell, so again we could use a`*`

operator if needed.

i.e:

`Some({ a: Int -> a + 3 }) apply Some(2)`

// => Some(5)

If you look carefully you will see that our operator only works in this specific order: `Option(function) apply Option(value)`

why? Because our extension function is defined in that order. Then, couldn’t I just make another extension function to work the other way around, like:

fun <A, B> Option<A>.`apply`

(o: Option<(A) -> B>) = {...}

fun <A, B> Option<(A) -> B>.`apply`

(o: Option<A>) = {...}

Technically not. Since Kotlin produces same code as Java would, it has to deal with our friend the type erasure. So basically those 2 functions would loose the generic types at compile time (and become just `Option`

), making them equal and therefore invalid. But here’s a trick, we could use a so called `dummyImplicit`

(and you can read why here) so it would look like:

fun <A, B> Option<A>.apply(f: Option<(A) -> B>,

dummyImplicit: Any? = null): Option<B> =

when (this) {

is Option.None -> Option.None

is Option.Some -> f.map { it(value) }}

This allows us to do:

Some(2).apply(Some({a: Int->a + 3}))`// => Some(5)`

But unfortunately it makes the infix impossible since infix functions only have one parameter :(

So, following our previous explanation, using *apply *can lead to some interesting situations. For example:

arrayOf<(Int) -> Int>({ it + 3 }, { it * 2 })applyarrayOf(1, 2, 3)

// => [ 4, 5, 6, 2, 4, 6 ]

Note:the original article now shows how Applicatives are more powerful than Functors in that they allow function application with multiple parameters. Again this is not feasible in vanilla Kotlin, but we can work around it by defining the function we want to handle in acurried way.

Here’s something you can do with Applicatives that you can’t do with Functors. How do you apply a function that takes two arguments to two wrapped values?

fun curriedAddition(a: Int) = { b: Int ->

a + b

}

`Some(3) map ::curriedAddition map Some(2)`

// => COMPILER ERROR

Applicatives:

Some(3) map ::curriedAddition apply Some(2)

// => Some(5)

Wait, what?? Let me break it down step by step:

Some(3) map ::curriedAddition

// => Some({ 3 + b })

Some({ 3 + b }) apply Some(2)

// => Some(5)

`Applicative`

pushes `Functor`

aside. “Big boys can use functions with any number of arguments,” it says. “Armed with map and apply, I can take any function that expects any number of unwrapped values. Then I pass it all wrapped values, and I get a wrapped value out! AHAHAHAHAH!”

fun curriedTimes(a: Int) ={b: Int->a * b

}

Some(3) map ::curriedTimes apply Some(5)

// => Some(15)

But wait, what if we want to go deeper?

Suppose we have a triple product function:

fun tripleProduct(a: Int, b: Int, c: Int) = a * b * c

We want to do the same as before but we don't want to manually curry it, so we have a curry function, in this case for 3 params:

fun <A, B, C, D> curry(f: (A, B, C) -> D): (A) -> (B) -> (C) -> D ={a-> {b-> {c->f(a, b, c)} } }

Thanks Ľuboš Mudrák for the suggestion!

Well, that's easy:

Some(3) mapcurry(::tripleProduct) apply Some(5) apply Some(4)

// => Some(60)

#### That’s it! Hope you enjoyed this second part as much as I did while writting it, remember that you can find all the code in the playground repo I created and hope to see you in the next and final series!

The third and final part is already available"

Hacker Noon is how hackers start their afternoons. We’re a part of the @AMI family. We are now accepting submissions and happy to discuss advertising & sponsorship opportunities.

If you enjoyed this story, we recommend reading our latest tech stories and trending tech stories. Until next time, don’t take the realities of the world for granted!