Я использую монадный трансформатор EitherT. Объединив его с монадой IO, я боюсь, что я получу исключение, и это не будет поймано.
Действительно, исключение просто проходит через:
import Control.Monad.Trans
import Control.Error
import System.Directory
main = runEitherT testEx >>= print
testEx :: EitherT String IO ()
testEx = lift $ removeFile "non existing filename"
Но EitherT
в противном случае подходит для счета, чтобы передать вызывающим абонентам ошибку. Поэтому я хочу использовать это, а не исключать исключения...
Я посмотрел на try
из Control.Exception:
try :: Exception e => IO a -> IO (Either e a)
Кажется, именно то, что я хочу, это поместилось бы в мой стек Iither IO... (возможно, с добавленным hoistEither
и, возможно, fmapL
, и он начинает выглядеть многословным). Но наивный lift $ try
doesn 't typecheck.
Я уверен, что эта проблема была решена тысячи раз, но я не могу найти никакой хорошей ссылки, описывающей эту точную проблему. Как это должно быть разрешено?
РЕДАКТИРОВАТЬ. "Как это должно быть решено", меня интересовало идиоматическое решение, каким будет стандартный способ справиться с этим в haskell. Из ответов до сих пор кажется, что идиоматический способ состоит в том, чтобы исключить исключения и обрабатывать их выше. Похоже, что бит-интуитивен, чтобы иметь два потока управляющих и обратных путей, но это, по-видимому, способ, которым это должно было быть сделано.