Given the following snippet:
fun returnsLeft() = "Nope".left()
fun returnsRight() = 1.right()
val testVal: Either<String, Int> = Either.fx {
val (_) = returnsLeft()
val (x) = returnsRight()
x
} // should be equal to "Nope".left(), but is equal to 1.right()
I would assume testVal equal to "Nope".left(), but it turns out to be equal to 1.right().
If I give a name to the value to which the return value of returnsLeft() is assigned, everything is fine. I.e.
fun returnsLeft() = "Nope".left()
fun returnsRight() = 1.right()
val testVal: Either<String, Int> = Either.fx {
val (someName) = returnsLeft()
val (x) = returnsRight()
x
} // equal to "Nope".left() as expected
Sounds like a weird compiler optimization to me. Try ! or bind() instead.
How exactly can ! and bind (I thought bind was replaced by fx) be used in this case?
not and component1 (which is ! and destructuring) are aliases to bind. This does indeed call returnsLeft as it should but the call to bind never happens. Changing to ! or bind works fine, just gives lots of warnings for unreachable code (as it should imo)
Btw this frequently crashes the compiler for me...
Thank you guys!
Both !returnsLeft() and returnsLeft().bind() work for me.
The _unreachable code_ warnings are fine, given, that it's all constants.
Although, coming from Haskell, I'd expect even
fun returnsLeft() = "Nope".left()
fun returnsRight() = 1.right()
val testVal: Either<String, Int> = Either.fx {
returnsLeft()
val (x) = returnsRight()
x
}
to work. Will this be possible at some point?
Thank you guys!
Both!returnsLeft()andreturnsLeft().bind()work for me.
The _unreachable code_ warnings are fine, given, that it's all constants.
Glad to help ^-^
Although I don't like this one bit, if a fix is easy (which I kind of doubt) we should fix it, however with the arrow plugin coming up this would be obsolete anyway I think, so maybe not worth wasting time on atm.
Although, coming from Haskell, I'd expect even
fun returnsLeft() = "Nope".left() fun returnsRight() = 1.right() val testVal: Either<String, Int> = Either.fx { returnsLeft() val (x) = returnsRight() x }to work. Will this be possible at some point?
Even in haskell this only works if x is of type Either<L, *>. For the suspend hack version of monad comprehensions I doubt that it will ever work that way, with the compiler plugin, maybe.
Maybe @raulraja can give a more definitive answer to that.
I have noticed this behaviour on other monad comprehensions as well. This definitly needs an entry somewhere (if it does not yet exist) that val (_) = !m is unsafe because m is likely not flatMapped
We plan to remove ! and () altogether because of this. Raul mentioned it a while ago and we didn't even get to the deprecation notice 馃檲
Comprehensions in November will replace all current infra related to continuations and monad continuations. I'm happy to proceed with whatever you decide but this is all gone then.
All comprehensions will be based in by as shown here https://github.com/arrow-kt/arrow-meta/blob/8882df9702cc57bf0e637fa8eeb8aef0a293fc3a/compiler-plugin/src/test/kotlin/arrow/meta/plugins/comprehensions/ComprehensionsTest.kt#L9
Yeah I thought so, if there is another release before it should be marked deprecated or something with a message indicating that fault but if not whatever.
Is this solved with release 0.10.3?
Is this solved with release 0.10.3?
I don't think we can. This is a compiler issue afaik. But since arrow-meta together with new and much better comprehensions is on the way (see rauls link above), and also because this is likely a hard problem to fix (on our side that is), the plan afaik is to ignore this (probably should mention this somewhere in the docs) and deprecate the usage of it in favor of the newer comprehensions.
Just asked because of
Comprehensions in November will replace all current infra related to continuations and monad continuations. [...]
But I guess the issue can be closed, then.
we are not there yet, we are gonna need a few more weeks to stabilize arrow meta with Fx.