Daniel TIefenauer
12/27/2023, 2:43 PMParseError if the string could not be parsed for some reason).
The function has the following properties
• the input string can be an Int or a Double . If the value can be parsed (happy path), a Either.Right<Int> is returned
• when passing a Double, it will be ceiled to the next integer value (so "42.1" will be parsed as 43)
• Double, both . and , are accepted as decimal separators. If this condition is not met, a Either.Left<ParseError.InvalidDecimalPoint> is returned.Double, the value must be within in the Interval [Int.MIN_VALUE, Int.MAX_VALUE] . If this condition is not met, a Either.Left<ParseError.ValueTooLow> resp. a Either.Left<ParseError.ValueTooHigh> is returned
• If the string could not be parsed for some other reason (e.g. because it contains non-numeric characters), a Either.Left<ParseError.NotANumber> is returned.
Based on the above constraints, the function's signature is String -> Either<ParseError, Int> .
I came up with the solution from the code snippet below, but I can't find a way to chain the eithers together. There's also some code duplication. Seems like there's a flatMapLeft function missing. Or am I missing something? What's the most elegant, Kotlin-idiomatic way to implement this?stojan
12/27/2023, 3:45 PMrecover -> https://apidocs.arrow-kt.io/arrow-core/arrow.core/recover.html when chaining these eithersstojan
12/27/2023, 3:46 PMintEither.recover { doubleEither }.recover { decimalPointEither }Daniel TIefenauer
12/27/2023, 3:54 PMimport arrow.core.recoverAdamW
12/27/2023, 7:27 PMeither builder and catch to transform exceptions to typed errors, see here for a comprehensive example: https://blog.rockthejvm.com/functional-error-handling-in-kotlin-part-3/
edit: in fact, you probably need to use nested catch if you want this in a single function. It’s perhaps simpler to split the ”parsers” and then chain them separately, likely with recoverYoussef Shoaib [MOD]
12/27/2023, 9:50 PMInvalidDecimalPoint and when I should raise NotANumber. The code here thus doesn't use NotANumber at all. Regardless, here's how I would do it:Youssef Shoaib [MOD]
12/27/2023, 9:52 PMeither and Either types with .bind() calls when necessary. I personally think the code in toIntBasedOnSpec is idiomatic Kotlin with Arrow.Daniel TIefenauer
12/28/2023, 8:01 AMInvalidDecimalPoint and NotANumber. I omitted it in my latest implementation. I tried to get it down to a single function without contexts (because context receivers show up as experimental and I don't want to use experimental features) and without Nullability (because I don't like the Elvis operator).
So far I got it down to this function, which nests the eithers using pattern matching in a when clause. However, I was hoping there would be a more readable/fluent way...
Btw: I now pushed the code to my Repo, where there's also an accompanying test suite to check the implementation: https://github.com/tiefenauer/mp-techlunch-kotlin-arrow/blob/main/src/main/kotlin/NumberParseMonad.ktYoussef Shoaib [MOD]
12/28/2023, 8:13 AM