Я как бы новичок в purescript, и я экспериментировал с эффектами и определенными асинхронными эффектами.
Одна из вещей, которые мне больше всего нравятся в FP и строгих компиляторах, таких как purescript, - это то, что он заставляет вас обрабатывать все возможные результаты, в частности, когда вы определяете, что что-то может выйти из строя. Если вы, например, используете Either, вам нужно указать программе, что делать, если у вас есть Right
ответ или ошибка.
Когда я впервые посмотрел на эффекты, мне понравилась концепция actions
и handlers
, и что, если часть вашего кода должна генерировать исключение (я полагаю, что это последний ресурс, который вы хотите использовать), вам нужно объявить его, используя что-то вроде
someAction :: forall eff. Eff (exception :: EXCEPTION | eff)
и что вы можете определить обработчик, который удаляет этот эффект, чтобы вы знали, что с этого момента вам не нужно заботиться об исключениях.
Но, проведя несколько базовых тестов с монадой Aff
и библиотекой purescript-node-fs-aff
, я получил несколько неожиданных результатов.
Если я сделаю что-то подобное
main :: forall e. Eff (console :: CONSOLE, buffer :: BUFFER, fs :: FS | e) Unit
main = do
_ <- launchAff $ readAndLog "./non-existing-file"
pure unit
readAndLog :: forall eff. String -> Aff (fs :: FS, console :: CONSOLE | eff) Unit
readAndLog path = do
str <- readTextFile UTF8 path
log str
Если файл не существует, программа прекратит генерировать исключение, и ничто не говорит мне, что этот код может дать сбой, и что я должен попытаться защитить свою программу от этого сбоя.
На самом деле я могу быть немного более оборонительным и использовать catchError
, но я ожидал, что, по крайней мере, компилятор выйдет из строя, заявив, что я не воспринимаю исключение как возможный побочный эффект.
main :: forall e. Eff (console :: CONSOLE, buffer :: BUFFER, fs :: FS | e) Unit
main = do
_ <- launchAff $ readAndLog "./non-existing-file" `catchError` (\e -> log ("buu: " <> message e))
pure unit
readAndLog :: forall eff. String -> Aff (fs :: FS, console :: CONSOLE | eff) Unit
readAndLog path = do
str <- readTextFile UTF8 path
log str
В идеале я хотел бы сделать что-то вроде Either
и нести ответственность за обработку конкретных ошибок, которые могут возникнуть в этой операции. Например, когда я читаю файл, я должен ожидать появления ошибки типа ENOENT
(файл не существует) или EACCES
(у вас нет доступа) и т. Д. Если я хочу проигнорировать конкретную причину и просто записать, что это не удалось, это мой выбор, но система типов должна заставить меня справиться с этим.
launchAff
глотает ошибки. Он должен требовать от вызывающего пользователя предоставить инструкции (то есть обратного вызова) о том, что делать с ошибками, но вместо этого он просто игнорирует их. - person Fyodor Soikin   schedule 21.03.2018