IO and suspend questions are so hot right now Tha...
# arrow
f
IO and suspend questions are so hot right now Thanks to the excellent reply to my previous question and reading around a bit more, I now feel like I understand IO/suspend better in practice But even as someone who's very fond of FP, I must admit I struggle to see the point a bit Like yes you can construct computations and map and filter and chain etc them in weird and wonderful ways but what's the practical actual use? I can make a strong case to FP skeptics for not using null, using result types instead of exceptions etc But I'd REALLY struggle to make any case at all for just coding vs creating an object of code and then calling .run
s
FP in my opinion has many goals, and it shares many goals with OOP. In a hybrid language like Kotlin, there is obviously a lot of overlap between the two as well. For example, in Kotlin it would be considered very unidiomatic to manually loop over a list to manually add transformed elements into a new list. Because Kotlin Std has
List#map
, but this is arguably an FP operator. Same with
suspend
, Kotlin brings it into the language as a feature so it becomes almost transparent to the user to use it within an OOP-styled project but
Continuation
and
IO
are also FP constructs. In this regard, Kotlin does a great effort to bring a lot of functional patterns into the language.
sealed class
,
data class
,
when
,
if as a statement
, etc are a couple of other things common in functional languages. So as you can see the line between these two is rather thin, and I'm a bit unsure what you mean with your question: "Like yes you can construct computations and map and filter and chain etc them in weird and wonderful ways but what's the practical actual use?" I'd say this is unrelated to FP, and using
map
&
filter
is just a way to write much clean code without having to write so much boilerplate. But to answer your final question:
But I'd REALLY struggle to make any case at all for just coding vs creating an object of code and then calling .run
One of the ideas behind using
IO
or
suspend
which I also already mentioned before is that you cannot call
IO
or
suspend
from regular code. Or in other words, if you mark all your side-effecting code with
suspend
the compiler doesn't allow to call it from
non-suspend
code. So the compiler can prevent you from making a mistake here. This allows you to easily split up your code is easy to test pure code with pure function. i.e.
map: (UserDto) -> User
and side-effecting code
fetch: suspend (id: Int) -> UserDto
. The point of calling
run
is to bridge both worlds with each other. It could also be defined as
operator fun <A> (suspend () -> A). invoke(): A
or
operator fun <A> IO<A>.invoke(): A
but that defeats the purpose of being explicit.
This is always a tricky question to answer since there might be different answers depending on the language you use and how much experience one has with FP.
r
In that answer questioning Odersky’s view if you look at each one of the items those are also properties of suspend functions.
☝️ 1
j
@Fred Friis nicely phrased.. same thoughts I had/have...still digesting answers and arrow's constructs... all in 'preparation' for these diskussions with FP skeptics 😄