我如何处理很多级别的缩进? [英] How do I deal with many levels of indentation?

查看:93
本文介绍了我如何处理很多级别的缩进?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  main = do 
inFH< p> - openFile...ReadMode
outFH< - openFile...WriteMode

forM myList $ \ item - >
...
if ...
then ...
else else
...
case ... of
Nothing - > ...
只需x - >做
...
...

代码很快飞到对,所以我想把它分成几块,例如使用 where 子句。问题是,这些 ... 中的许多都包含读/写语句给两个句柄 inFH outFH ,并使用,其中语句将会在上下文之外呈现这两个名称。我必须在每次使用 where 语句时发送这两个变量。



有没有更好的方法处理这个问题?在很多情况下,这些深度嵌套的缩进是深度嵌套错误检查的结果。如果这对你有帮助,你应该看看 MaybeT 及其大哥哥 ExceptT 。这些提供了一种干净的方式,可以将我们做什么假设一切正确的代码与我们在出现问题时做了什么代码分开。在你的例子中,我可能会写:

  data CustomError = IfCheckFailed | MaybeCheckFailed 

main = handleErrors< =< runExceptT $ do
inFH< - liftIO $ openFile ...
outFH< - liftIO $ openFile ...
for myList $ \\ \\item - > (...)(throwError IfCheckFailed)
...
x< - liftMaybe MaybeCheckFailed ...
...

liftMaybe :: MonadError em => e - >也许是 - > m a
liftMaybe err = maybe(throwError err)return

handleErrors :: CustomError a - > IO a
handleErrors(Left err)=大小写错误
IfCheckFailed - > ...
MaybeCheckFailed - > ...
handleErrors(正确成功)=返回成功

请注意,我们仍然会增加缩进在 forM 循环中;但其他检查在 main 中in-line完成,并在 handleErrors 。


I am writing a script that has a very logically complicated loop:

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

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

The code soon flies to the right, so I was thinking breaking it into pieces, using for example where clauses. The problem is, many of these ... contain reading/writing statements to the two handles inFH and outFH, and using a where statement will render those two names out of context. I would have to send in these two variables everytime I use a where statement.

Is there a better way of dealing with this?

解决方案

In many cases, these deeply-nested indentations are the result of deeply-nested error checking. If that's so for you, you should look into MaybeT and its big brother ExceptT. These offer a clean way to separate the "what do we do when something went wrong" code from the "what do we do assuming everything goes right" code. In your example, I might write:

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

Notice that we still increase indentation at the forM loop; but the other checks are done "in-line" in main, and are handled all at the same indentation level in handleErrors.

这篇关于我如何处理很多级别的缩进?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆