如何处理多级缩进?
我正在编写一个脚本,它有一个逻辑上非常复杂的循环:
main = do
inFH <- openFile "..." ReadMode
outFH <- openFile "..." WriteMode
forM myList $ \ item ->
...
if ...
then ...
else do
...
case ... of
Nothing -> ...
Just x -> do
...
...
代码很快就飞到了右边,所以我正在考虑将其分成几部分,例如使用 where
子句。问题是,其中许多 ...
包含对两个句柄 inFH
和 outFH
的读/写语句,并使用 where
语句将在上下文之外呈现这两个名称。每次使用 where
语句时,我都必须发送这两个变量。
有更好的方法来处理这个问题吗?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在许多情况下,这些深层嵌套的缩进是深层嵌套的错误检查的结果。如果您也是这样,那么您应该研究一下
MaybeT
及其老大哥ExceptT
。这些提供了一种干净的方法来将“出现问题时我们做什么”代码与“假设一切正常我们做什么”代码分开。在您的示例中,我可能会写:请注意,我们仍然在
forM
循环处增加缩进;但其他检查是在main
中“内联”完成的,并且在handleErrors
中以相同的缩进级别进行处理。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 brotherExceptT
. 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:Notice that we still increase indentation at the
forM
loop; but the other checks are done "in-line" inmain
, and are handled all at the same indentation level inhandleErrors
.虽然有更好的方法可以解决您的具体问题(请参阅eg 丹尼尔·瓦格纳(Daniel Wagner)的答案),您可以始终使用
>让
在任意范围内引入新名称。这是一个公认的毫无意义的演示:While there likely are nicer ways to solve your concrete problem (see e.g. Daniel Wagner's answer), you can always use
let
to introduce a new name within an arbitrary scope. Here is an admittedly nonsensical demo:您应该使用任何其他编程语言做同样的事情。功能应该易于理解。这通常意味着,如果它很长,则没有太多的控制流,否则将其分为单独的功能。
因此,主要可能看起来像:
You should do the same thing you would have done with any other programming language. Functions should be easy to understand. This typically means that if it is long there isn't a lot of control flow, otherwise split it up in to separate functions.
So main might look like: