curious to hear other opinions of Arrow users on t...
# arrow
s
curious to hear other opinions of Arrow users on this one -> https://github.com/arrow-kt/arrow-core/issues/114
r
I replied regarding your concern on Option
we can move it to another module so there is no migration issues
👍 1
s
Thanks @raulraja, I appreciate it. But I am still interested in hearing other opinions. Maybe I am overreacting and no one cares 😁
r
what are your concerns about demoting Option?
s
I'm fine with moving it to another module, no problems with that
r
We have a vision around delimited continuations that changes the way we program in FP. If you’d like to hear more about it or are interested in an informal chat I’m happy to discuss this over meet.
I would like to eliminate much more than Option to make it all more Kotlin idiomatic. flatMap, followedBy, ap, etc and all those other functions are also problematic. They add indirection that in Kotlin is pointless in most cases.
s
I fully support that direction.... my concerns are not strictly technical, but more people/social Arrow had a type in the core package that was an alternative to
null
. People new to FP starting with Arrow would probably start using it by using
Option
/`Try` /`Either` So newcomers to FP would use
Option
instead of
null
Try
was deprecated some time ago, and will be removed. And the migration story there could have been better. I know some people who didn't understand the reasoning behind this, and actually moved away from Arrow because of it Now back to
Option.
list.first()
throws an Exception in case of an empty list. Break RT and comes with all the drawbacks from it.
list.firstOption()
is RT and comes with all the benefits. It is significantly better than
first()
list.firstOrNull()
is even better. No wrapping, more idiomatic and probably more performant. It is better than
firstOption()
but not by much. Both are RT and compose really well. Removing all usages of
Option
and replacing them with Nullable types might take significant effort in a larger codebase for exactly 0 business value. If performance was critical people would probably not use
Option
in the first place. So basically my worries are: • the alternative is not significantly better • migration might take time with no clear benefits • people might feel they are doing FP wrong I think putting it in a separate module would make it clear that
Option
is not recommended in the future and promote Nullable types. It will also enable people to migrate incrementally (or even not migrate, but coexist, writing new code with nullable types, keeping the old with Option).
happy to jump on a meet if you need further clarifications
f
My team uses Arrow and I'd like to mention we do prefer Option to Kotlin's nullable types. Option is much more clear and idiomatic FP than Kotlin's kind of not great implementation of nullable types. Granted, Option.map and flatMap and nullable type ?.let{} are functionally equivalent but the former just reads so much better, and we want not just functor and monad but applicative as well, no? Eg given a List<Option<Foo>>, we can use applicative to declaratively and with referential transparency etc etc (you know the usual FP sales pitch) turn it into an empty list if it contains a single non-populated option, or a list of Foo if all options in the list are populated. With Kotlin nullable types I don't think you could do it as declaratively and elegantly. Actually, even if you could, it's kind of beside the point... To me, the point is, Option has been designed from scratch to be an FP style Maybe type with all that comes with that in terms of it being a functor, applicative functor, monad etc etc whereas while Kotlin nullable types in some ways are functionally equivalent, a nullable type doesn't implement a Functor interface, or a Monad interface, or an Applicative interface, and when it behaves like it does, it's mostly kind of by accident driven by a pragmatic need, not any real understanding of reusable, lawful FP abstractions.
r
@stojan makes sense and we can move to another module so people can still use it and there is no need for migration beside the dependency and perhaps imports.
👍 1
@Fred Friis we understand your point but Kotlin has a unique feature based on delimited continuation that allows us to reencode all these data types in a more idiomatic, succinct and performant way than the Haskell or Scala encoding based on wrappers. I disagree that “this is the FP style”, being purely functional is FP regardless of nested wrapped or direct style. To the point of nullable versus option the only remaining use case for Option is when you use Kind in Arrow to materialize a program to Option which in practice nobody does because it’s a strict datatype. It’s the same story as suspend vs IO. We are a FP companion to the std lib and our commitment is to remain first correct and functional and then idiomatic and performant with Kotlin. Having said this I’ happy to jump on a call to explain the rationale and direction on why these data types are not needed and they increase the surface newbies need to learn when they come to Arrow.
I also discussed with Simon yesterday a new approach to remove Kind all together while maintaining polymorphism
F[_] in Kotlin can be expressed as a continuation as well and become a top interface that does not require higher kinded types
These changes will change the size of Arrow notoriously and for nostalgic that want to continue using our initial Scala ad Haskell influence we plan on moving relevant data types there but as library maintainers we can’t promote an encoding that is more difficult to maintain and orders of magnitude less performant as they use in Scala.
In the case of Haskell the runtime optimizes for these kinds of encoding but everyone in Scala is paying heavy allocation costs for this style of FP which makes it only suitable in places where your speed does not matter because you are bound to I/O
Since Kotlin has support for delimited continuations all monads can be interleaved in direct style differentiating between strict and lazy monads and providing a faster and specialized runtime for each instead of desugaring to flatMap.
This is the direction Kotlin is already going. Nullability (Option), suspend (IO) in all of them there is no Functor hierarchy because you are already in direct applicative style (imperative) with the same safety guarantees as wrapped style.
f
Fair enough, I do understand where you're coming from 👍 and Arrow will continue to be a godsend no matter
🙏 1