tim
06/02/2020, 9:12 AMsimon.vergauwen
06/02/2020, 9:18 AMmap
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.
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
.aballano
06/02/2020, 9:19 AMflatmap = map + flatten
tim
06/02/2020, 9:35 AMsimon.vergauwen
06/02/2020, 9:35 AMtim
06/02/2020, 9:36 AMtim
06/02/2020, 10:34 AMstojan
06/02/2020, 11:42 AMtim
06/02/2020, 12:27 PMAttila Domokos
06/02/2020, 5:06 PMOption
and Either
type. It's really simple, and looking at the implementation tells you how it works. This is the code for `Option`:
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)
}
}
}
Attila Domokos
06/02/2020, 5:09 PMflatMap
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.tim
06/02/2020, 6:21 PMAttila Domokos
06/02/2020, 6:23 PMtraverse
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.tim
06/02/2020, 6:25 PMAttila Domokos
06/02/2020, 6:26 PMAttila Domokos
06/02/2020, 6:28 PMMaybe
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...tim
06/02/2020, 6:29 PMtim
06/02/2020, 6:30 PMAttila Domokos
06/02/2020, 6:30 PMtim
06/02/2020, 6:31 PMtim
06/02/2020, 6:32 PMAttila Domokos
06/02/2020, 6:32 PMAttila Domokos
06/02/2020, 6:33 PMtim
06/02/2020, 6:34 PMAttila Domokos
06/02/2020, 6:34 PMAttila Domokos
06/02/2020, 6:34 PMtraverse
function on an Either
type yourself.Attila Domokos
06/02/2020, 6:36 PMtim
06/02/2020, 6:37 PMtim
06/02/2020, 6:40 PM