Во многих случаях эти глубоко вложенные углубления являются результатом глубоко вложенной проверки ошибок. Если это так, вы должны изучить MaybeT
и его старшего брата ExceptT
. Они предлагают чистый способ отделить код «что мы делаем, когда что-то пошло не так» от кода «что мы делаем, если все идет правильно». В вашем примере я могу написать:
data CustomError = IfCheckFailed | MaybeCheckFailed
main = handleErrors <=< runExceptT $ do
inFH <- liftIO $ openFile ...
outFH <- liftIO $ openFile ...
forM myList $ \item -> do
when (...) (throwError IfCheckFailed)
...
x <- liftMaybe MaybeCheckFailed ...
...
liftMaybe :: MonadError e m => e -> Maybe a -> m a
liftMaybe err = maybe (throwError err) return
handleErrors :: Either CustomError a -> IO a
handleErrors (Left err) = case err of
IfCheckFailed -> ...
MaybeCheckFailed -> ...
handleErrors (Right success) = return success
Обратите внимание, что мы все еще увеличиваем отступ в цикле forM
; но другие проверки выполняются «in-line» в main
и обрабатываются на одном уровне отступов в handleErrors
.
Похоже, вы решили свою собственную проблему.
Edit: Лично я бы перечислил сборки, одну за другой, загрузил их и поискал интерфейс. Делать это на основе файлов, а не того, что делает AppDomain.