Haskell 如何处理多个级别的缩进?
我正在编写一个逻辑上非常复杂的循环脚本:Haskell 如何处理多个级别的缩进?,haskell,indentation,code-organization,Haskell,Indentation,Code Organization,我正在编写一个逻辑上非常复杂的循环脚本: main = do inFH <- openFile "..." ReadMode outFH <- openFile "..." WriteMode forM myList $ \ item -> ... if ... then ... else do ... ca
main = do
inFH <- openFile "..." ReadMode
outFH <- openFile "..." WriteMode
forM myList $ \ item ->
...
if ...
then ...
else do
...
case ... of
Nothing -> ...
Just x -> do
...
...
main=do
通知。。。
只需x->do
...
...
代码很快就飞到了右边,所以我想用where
子句将代码分成几部分。问题是,其中许多..
包含对两个句柄inFH
和outph
的读/写语句,使用where
语句将使这两个名称脱离上下文。每次使用where
语句时,我都必须发送这两个变量
有没有更好的方法来处理这个问题?你应该像对待其他编程语言一样做同样的事情。函数应该易于理解。这通常意味着,如果它很长,则没有太多的控制流,否则将其拆分为单独的函数 所以main可能看起来像:
main = do
inFH <- openFile ...
outFH <- openFile ....
mapM prcoessItem myList
main=do
inFH在许多情况下,这些深嵌套缩进是深嵌套错误检查的结果。如果对你来说是这样的话,你应该调查一下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
data CustomError=IfCheckFailed |可能被检查失败
主=手柄错误m a
liftMaybe err=可能(投掷者错误)返回
handleErrors::自定义错误a->IO a
handleErrors(左错误)=案例错误
如果检查失败->。。。
可能是检查失败->。。。
handleErrors(右成功)=返回成功
注意,我们仍然在表单
循环中增加缩进;但是其他检查是在main
中“串联”完成的,并且在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打印“条”
_->打印“baz”
表格[1..10]$\item->do
打印项目
子作用
Um,这与规定的不在任何地方通过inFH
和outh
的要求非常不一致。谢谢。这是我看过头了的东西。然而,我不喜欢在这里使用let
,因为它颠倒了阅读顺序——我首先定义了步骤的一部分,然后是流程的其余部分。我也不喜欢给逻辑流的一部分命名,这也是我想避免使用where
的另一个原因。