Hi folks, can anyone recommend a good article on flatMap vs map? I'm finding that i'm almost always ...
t
Hi folks, can anyone recommend a good article on flatMap vs map? I'm finding that i'm almost always using map in my code and so suspect I'm missing something as I learn FP
s
They have different signatures and thus different powers. While
map
takes a function of the shape
(A) -> B
,
flatMap
takes a function of the shape
(A) -> Kind<F, B>
. If we look at this for
List
that means.
Copy code
listOf(1, 2, 3).map { it + 1 }
 // [2, 3, 4]

listOf(1, 2, 3).flatMap { listOf(it, it + 1) }
 // [1, 2, 2, 3, 3, 4, 4, 5]
With
flatMap
here we can return 2 items instead of 1 since we can return the result inside
List
. The same is true for all data types. For example with Option that means using `map`` I always return a value, but in case of
flatMap
I could also return
Option.None
.
🙏 2
🔝 2
a
also ->
flatmap = map + flatten
👌 2
🙏 3
☝️ 3
t
Ahh okay that makes sense ... so I use flatMap when the lambda returns a nesting ... So, for example, if the lambda returned an Either I can use flat map to unpack the inner Ether so I don't end up with nested Eithers?
💯 3
s
Exactly!
t
great thanks :)
... and a few minutes later I needed flatMap 🙂
😂 1
s
I recommend this talk on the subject: https://fsharpforfunandprofit.com/rop/
🔝 3
t
thanks will add it to my list
a
You could also build your own
Option
and
Either
type. It's really simple, and looking at the implementation tells you how it works. This is the code for `Option`:
Copy code
sealed class Option<A> {
    abstract val value: A

    abstract fun <B> map(f: (A) -> B): Option<B>
    abstract fun <B> flatMap(f: (A) -> Option<B>): Option<B>

    class None<A>: Option<A>() {
        override fun <B> map(f: (A) -> B): Option<B> = None()
        override fun <B> flatMap(f: (A) -> Option<B>): Option<B> = None()
        override fun equals(other: Any?): Boolean {
            if (this === other) return true
            if (javaClass != other?.javaClass) return false
            return true
        }

        override val value: A
            get() = TODO("Not yet implemented")
    }

    data class Some<A>(val valueInput: A): Option<A>() {
        override fun <B> map(f: (A) -> B): Option<B> = Some(f(valueInput))
        override fun <B> flatMap(f: (A) -> Option<B>): Option<B> = f(valueInput)

        override val value: A
            get() = valueInput
    }

    companion object {
        operator fun <A> invoke(a: A? = null): Option<A> =
                when(a) {
                    null -> None()
                    else -> Some(a)
                }
    }
}
🤘🏼 1
Imagine you don't have
flatMap
and you tried to use
map
for a function with
(A) -> Option<A>
, you get
Option<Option<A>>
. You need to flatten that with
flatMap
to get
Option<A>
. Seeing a basic implementation will tell you a lot about its behavior.
🙏 1
👏🏼 1
t
Thanks for this. Ya I need to spend more time in the source code. Option makes a lot of sense. I'll dig into either tomorrow.
a
Arrow's source code could be a lot more complex, I have not looked. Anybody who wants to understand the concept of Arrow should read the book "The Joy of Kotlin", it's a fantastic intro book showing you how to build these types, understanding Lazy, what a
traverse
is. I am using ideas from this book to teach core FP concepts, and once the team feels comfortable, I'll pull out Arrow, as a great library that does (and many other things) for you.
t
I was about to ask if anyone had a book recommendation 😂
a
☝️
I am halfway through the book, but it's eye opening. Here are the examples I have completed so far. I've built my own
Maybe
and
Either
in Haskell (for learning purposes) and the fact that you can do it in Kotlin with ease tells you a lot about the language. I wish more book examples would use TDD...
t
It's it a "pure" FP book?
One area that's unclear to me, is how mixing different paradigms is going to turn out!
a
I am not sure about "pureness", but it's the best book I've found so far describing FP principles.
t
I have lots of code that follows a more OO approach, and currently I can't imagine doing away with OO completely
From what you've read so far, does the book touch on that?
a
Whatever fits your team I think. The folks I am working with are scared of FP and the "complexity" of it. I am thinking of writing certain components (like API and dataaccess) in more object oriented style, but the "orchestration" logic is functional.
Tim, that's why included the examples from my GitHub account.
🙏 1
t
Oh perfect I'm on my phone currently but will check it out tomorrow
a
Take a look at the "Table of Contents", look at the examples.
Nothing teaches you better than building a
traverse
function on an
Either
type yourself.
It's a demanding book, you must type in the examples in your editor and run them to understand them.
t
Thanks, that's useful to know
👍 1
Okay just bought the book
😂 1