Brief, possibly dumb question: I'm fairly new to ...
# arrow
g
Brief, possibly dumb question: I'm fairly new to Kotlin -- but not to programming, or to the fundamentals of FP (ADT's, higher-order functions, whatnot. No clue about monoids, endofunctors and the likes though, bit over my head) Am curious about the comparison between Arrow's
Option<T>
and Kotlin's
Result<T>
(which I know Kotlin devs have said not to use directly, though not entirely sure why) And similarly for things like
.runCatching { }
Has anyone transitioned from using the basic FP primitives available in Kotlin stdlib to using mostly/exclusively Arrow, and could share thoughts/opinions and experiences? Would be grateful 🙏 Thank you!
r
Hi @Gavin Ray and welcome to Kotlin and Arrow! 🙂.
Option<T>
could be compared to nullable types in the sense that it models having a value or the absence of it. Option is useful in cases where you want an explicit box like ReactiveX Stream that otherwise use
null
not representing the absence of values as signal or interruption value. Result<T> models
Throwable
or
A
where
A
is the expected outcome. In this sense it could be compared to
Either<Throwable, A>
. Either , part of Arrow, is like result but parametric in the error case so in addition to Throwable you can also use your own error types that don’t need to be necessarily exceptions. The main difference between
Result
and
Either
is that Result aside from being fixed to Throwable receives special treatment by the Kotlin compiler codegen and it’s like an inline/value class (more efficient in terms of allocations and boxing). There is a proposal to extend this inlining capabilities to the lang as a feature for sealed value classes and when that happens then we may consider making Either and Option also a value class similar to Result. I think Result has been discouraged from use because value/inline classes are experimental until fully developed it’s not safe to use types like Result. Result is heavily used though in the internals and codegen of suspend funs in Kotlin. Arrow does not really attempt to replace what’s on the standard lib but complement it. We will include support for Result as we have for nullable types in terms of monad comprehensions and other features once it’s recommended for use. Here is some links in case you have not run into these yet. Either, Option and error handling with arrow https://arrow-kt.io/docs/patterns/error_handling/ Either https://arrow-kt.io/docs/apidocs/arrow-core/arrow.core/-either/ Validated https://arrow-kt.io/docs/apidocs/arrow-core/arrow.core/-validated/ Comprehensions and monads https://arrow-kt.io/docs/patterns/monad_comprehensions/ https://arrow-kt.io/docs/patterns/monads/
🙏 1
As for monoids, endofunctors, Arrow only includes a basic set of type classes like Semigroup (an associative operation) and Monoid (and associative operation and an empty element). Functors, Monads and others were removed from Arrow because they are not representable in the Kotlin type system because it lacks support for higher kinded types and hacking it imposes in the user the burden of casting and doing tricks to get types to align.
g
Thanks so much for the comprehensive overview and resources! The bit on error handling at first look seems to be particularly helpful
Result aside from being fixed to Throwable receives special treatment by the Kotlin compiler codegen and it’s like an inline/value class (more efficient in terms of allocations and boxing). There is a proposal to extend this inlining capabilities to the lang as a feature for sealed value classes and when that happens then we may consider making Either and Option also a value class similar to Result.
Ah, that is a bummer, I do hope this happens. Would be nice to have that same flexibility + power in userland, and probably critical for high-performance software
We will include support for Result as we have for nullable types in terms of monad comprehensions and other features once it’s recommended for use.
Oh this is really neat to hear! So people who already have code which may be a sequence of
Result<T>
values, like:
Copy code
val x: Result<A> = tryGetX()
// code for handling result outcome

val y: Result<A> = tryGetY()
// code for handling result outcome

val z = x + y
Will be able to do it something like this, where they'll be able to refactor and just take advantage of Arrow to write EG?
Copy code
val z = let {
  x = tryGetX()
  y = tryGetY()
  y + z
}
s
We’ve discussed adding a computation block for
Result<A>
so that you can do:
Copy code
val z = result {
  val x = tryGetX().bind()
  val y = tryGetY().bind()
  x + y
}
but we probably also want to add a couple extensions to make the same API available over
Result<A>
as we have for
Option
,
Either
etc.
☝️ 1
👀 1
m
Usually it is better to use Kotlins nullable types, "let" etc. instead of Option to handle them.
☝️ 1