haskell - 如何处理许多级别的压痕?

标签 haskell indentation code-organization

我正在编写一个逻辑上非常复杂的循环的脚本:

main = do
    inFH <- openFile "..." ReadMode
    outFH <- openFile "..." WriteMode

    forM myList $ \ item ->
        ...
        if ... 
            then ...
            else do
                ...
                case ... of
                    Nothing -> ...
                    Just x  -> do
                        ...
                            ...

该代码很快就会向右移动,因此我正在考虑使用where子句将其分成几部分。问题是,其中许多...包含对两个句柄inFHoutFH的读/写语句,并且使用where语句会使这两个名称脱离上下文。每当我使用where语句时,我都必须发送这两个变量。

有没有更好的方法来解决这个问题?

最佳答案

在许多情况下,这些深度嵌套的缩进是深度嵌套的错误检查的结果。如果是这样,您应该研究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循环中增加缩进;但是其他检查是在main中“内联”完成的,并且都在handleErrors中以相同的缩进级别进行处理。

关于haskell - 如何处理许多级别的压痕?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33005903/

相关文章:

haskell - Haskell 中的 "Lazy IO"?

haskell - 如何模拟货币、货币和在货币之间交换货币的银行?

haskell - 顶层的裸露表达用于简单的 Template Haskell 实验

coding-style - 如何在 Xcode 6.1 中更改花括号样式?

php - mVc 世界中的 HTML 缩进

haskell - [安全] 标记在 ghci 中是什么意思?

perl - @INC 中的错误 : Can't locate File/HomeDir. pm

python - 创建一组 Python 类

python - 将所有测试文件收集到一个文件夹中更好,还是让它们分发到各处更好?

CSS Transitions 代码组织