Эффекты использовать для обертывания нечистых методов?
Я пытаюсь понять, как использовать эффект монады (cats.effect.IO
или же scalaz.IO
не имеет значения). Представьте, что у меня есть следующий метод:
def extract(str: String): String = {
if(str.contains("123"))
"123"
else
throw new IllegalArgumentException("Boom!")
}
Так как этот метод нечист (вызывает исключение), и мне нужно объединить его результат с другим эффективным вычислением (network-IO), будет хорошей практикой просто обернуть его в IO
следующее:
def extract(str: String): IO[String] = IO {
if(str.contains("123"))
"123"
else
throw new IllegalArgumentException("Boom!")
}
Это общий случай использования монад Эффекта?
1 ответ
Уместно ли это или нет, зависит от того, что вы хотите выразить.
Это не как твой первый def extract(str: String): String
-метод определения как-то недопустим: вы просто подметаете все исключения и побочные эффекты под ковриком, чтобы они не были видны в подписи. Если это не имеет отношения к вашему текущему проекту, и если допустимо, что программа просто аварийно завершает работу с длинной трассировкой стека брошенного исключения, то сделайте это без проблем (легко представить одноразовые одноразовые сценарии, где это будет подходящее).
Если вместо этого вы объявляете def extract(str: String): IO[String] = IO { ... }
, то вы хотя бы можете увидеть в подписи, что функция extract
может сделать что-то нечистое (исключение, в данном случае). Теперь возникает вопрос: кто отвечает за работу с этим исключением или где вы хотите иметь дело с этим исключением? Учтите это: если выдается исключение, оно будет появляться в вашем коде в строке, где что-то вроде yourProgram.unsafeRunSync()
вызывается. Есть ли смысл иметь дело с этим исключением там? Может, да, а может и нет: никто не может тебе сказать. Если вы просто хотите поймать исключение на верхнем уровне в вашем main
, войдите и exit
тогда это уместно.
Однако, если вы хотите немедленно разобраться с исключением, у вас есть лучшие варианты. Например, если вы пишете метод, который запрашивает имя файла, то пытается extract
что-то из этого названия, и, наконец, делает некоторые IO
на файлы, то возвращаемый тип IO[String]
может быть слишком непрозрачным. Вы можете использовать другую монаду (Option
, Either
, Try
и т. д.) для представления неудачной добычи. Например, если вы используете Option[String]
как тип возврата, вам больше не придется иметь дело с неясным исключением в тысяче миль от вас main
метод, но вместо этого вы можете иметь дело с ним немедленно, и, например, неоднократно запрашивать новое имя файла.
Все упражнение несколько похоже на выработку стратегии работы с исключениями в целом, только здесь вы явно выражаете это в сигнатурах типов ваших методов.