Comments 13
Почему Expected?
Это ведь классический Either. Зачем вводить какие-то свои понятия?
Это ведь классический Either. Зачем вводить какие-то свои понятия?
Я вот тоже не понял. Ведь по сути, вавровский Try — это и так Either, содержащий либо результат, либо исключение (не параметризованное, т.е. Exception). И его можно к Either преобразовать, для этого есть метод toEither. А если хочется параметризованный — то Either к нашим услугам.
Можно применять Either. Названия и прототип для Expected<T, E> я взял с класса std::experemental::expected<T, E>, который планируется добавить в С++23 стандарт.
Например, в языке Scala для этого используется определенный класс Try.
На мой взгляд
Try
не самый удобный инструмент для обработки ошибок в Scala, см. например github.com/scala/bug/issues/6284. Лично мне больше по душе тайпкласс MonadError, где ошибка параметризована.Это же вроде проблема конкретной реализации в скале, а не функциональной обработки ошибок как таковой?
Все верно, это by design. Я имел ввиду, что если у нас есть чистая функция (взята с потолка):
то использовать
Это делает использование
def doSth[F[_]: MonadError[?[_], Throwable]](): F[Int] = for {
i <- Applicative[F].pure(10)
} yield i + 1
то использовать
Try
в качестве F
не получится, т.к. Try
нарушает правила функтора. А вот Either
очень даже подойдет: doSth[Try]() // не компилируется, нет нужного инстанса, т.к. нарушено правило
doSth[Either[Throwable, ?]]() //Ok
Это делает использование
Try
в функциональном как минимум проблематичным.>Но увы, в данный момент, чтобы работать с исключения в функциональном стиле можно использовать библиотеку Vavr или писать свои классы на подобии к Expected.
Почему увы-то?
Почему увы-то?
def inputStreamForURL(url: String): Try[Try[Try[InputStream]]]
В скале нет flat Map? :)
def inputStreamForURL(url: String): Try[Try[Try[InputStream]]] = parseURL(url).map { u =>
Try(u.openConnection()).map(conn => Try(conn.getInputStream))
}
Try[Try[Try
просто ужасен, можно ведь просто написать:
def inputStreamForURL(url: String): Try[InputStream] = Try {
parseURL(url).map(_.openConnection()).map(_.getInputStream())
}
У этих методов совершенно разная семантика. Throw это не просто результат функции, а именно раннее завершение всей цепочки вызовов до соответствующего catch-блока. Expected/Try — это урезанная семантика checked exception, в которой нельзя например выкидывать эксепшны разного типа (throws E1, E2). Так делается, потому что во многих функциональных языках нет другой альтернативы. В Java функциональщина всегда будет являться инородным телом и добавит бойлерплейта.
- Причём здесь Kotlin?
- Чего в результате вы хотели добиться по сравнению с обычными try-catch? (которые в Kotlin, кстати, являются выражениями)
Sign up to leave a comment.
Обработка ошибок в функциональном стиле в Java