繁体   English   中英

如何处理多级缩进?

[英]How do I deal with many levels of indentation?

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

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 ”完成,并且在handleErrors中以相同的缩进级别handleErrors

虽然可能有更好的方法来解决您的具体问题(例如参见 Daniel Wagner 的回答),但您始终可以使用let在任意范围内引入新名称。 这是一个公认的荒谬演示:

main = do
    inFH <- return "inf"
    outFH <- return "ouf"

    let subAction = do
            if length inFH > 2
                then print "foo"
                else subSubAction

        subSubAction = case outFH of
            [] -> print "bar"
            _ -> print "baz"

    forM [1..10] $ \ item -> do
        print item
        subAction

您应该做与使用任何其他编程语言所做的相同的事情。 函数应该易于理解。 这通常意味着如果它很长,则没有很多控制流,否则将其拆分为单独的功能。

所以主要可能看起来像:

main = do
    inFH <- openFile ...
    outFH <- openFile ....

    mapM prcoessItem myList

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM