This is a translation of Functors, Applicatives, And Monads In Pictures from Haskell into Kotlin . Actually this is a translation of another translation from Haskell to Swift . I read through the original post and I found it really interesting for learning new concepts of FP, so I decided to do an additional translation (having also some fun in the way). I also wanted to see how far can Kotlin get compared to Swift :) If you enjoy this post be sure to say thanks to the author of the original version: Aditya Bhargava , @_egonschiele on Twitter. Here’s a simple value: And we know how to apply a function to this value: 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 box that you can put a value in: Now when you apply a function to this value, you’ll get different results . This is the idea that Functors, Applicatives, Monads, Arrows etc are all based on. The data type defines two related contexts: depending on the context Option Option Note: the pictures use Maybe (Just | None) from Haskell, which correspond to a custom Kotlin’s (Some | None) implementation. sealed class Option<out A> {object None : Option<Nothing>()data class Some<out A>(val value: A) : Option<A>() } In a second we will see how function application is different when something is a versus a . First let’s talk about ! Some(T) None Functors Functors When a value is wrapped in a context, you can’t apply a normal function to it: This is where comes in ( in Haskell). is from the street, is hip to contexts. knows how to apply functions to values that are wrapped in a context. For example, suppose you want to apply a function that adds 3 to . Use : map fmap map map map Some(2) map fun sumThree(n: Int) = n + 3 Option.Some(2).map(::sumThree) // => Some(5) or with a simple syntax using an anonymous lambda: Option.Some(2).map shows us how it’s done! But how does know how to apply the function? Bam! map map Just what is a Functor, really? A Functor is any type that defines how ( in Haskell) applies to it. Here’s how works: map fmap map So we can do this: Option.Some(2).map And magically applies this function, because is a Functor. It specifies how applies to s and s: map Option map Some None inline fun <B> map(f: (A) -> B): Option<B> = when (this) {is None -> thisis Some -> Some(f(value))} Here’s what is happening behind the scenes when we write : Option.Some(2).map { it + 3 } So then you’re like, alright , please apply to a ? map { it + 3 } None Option.None.map { it + 3 }// => None Well, there's a gotcha here since the code above doesn't compile. Why? Well because in this case None doesn't have a proper type, so you cannot do a plus with type . But it should be fine because you normally won't write that code but something like: Nothing val option: Option<Int> = someCallThatMightReturnNone()option.map { it + 3 }// => None Like Morpheus in the Matrix, knows just what to do; you start with , and you end up with ! is zen. Now it makes sense why the type exists. For example, here’s how you work with a database record in a language without : map None None map Option Option val post = Post.findByID(1)return post?.title But in Kotlin using the functor: Option findPost(1).map(::getPostTitle) If returns a post, we will get the title with . If it returns , we will return ! findPost(1) getPostTitle None None We can even define as an infix function for ( in Haskell), and do this instead: map <$> inline infix fun <B> map(f: (A) -> B): Option<B> { ... } (1) map ::getPostTitle findPost Note: we have to use just _map_ because _<$>_ wouldn't compile. Another option would be to override a common operator like _/_ or _*_ Here’s another example: what happens when you apply a function to an array? Arrays are functors too*! *Basically Kotlin provides an extension function to all iterables in the form: inline fun <T, R> Iterable<T>.map(transform: (T) -> R): List<R> {..} Okay, okay, one last example: what happens when you apply a function to another function? { a: Int -> a + 2 } map { a: Int -> a + 3 } // => ??? Here's a function: Here’s a function applied to another function: The result is just another function! typealias IntFunction = (Int) -> Int So functions can be Functors too! When you use on a function, you’re just doing function composition! map Well, that's it for today, I hope you got the idea about what's a Functor. Since the original post was pretty long, I'll continue in the next series with Applicatives. Now go try write some Functors in Kotlin! Wanna play around with the code? Take a look at https://github.com/aballano/FAM-Playground Want more? Go try applicatives in the second part! _This is a translation of Functors, Applicatives, And Monads In Pictures from Haskell into Kotlin._medium.com Kotlin Functors, Applicatives, And Monads in Pictures. Part 2/3
Share Your Thoughts