Haskell 中的代码块未按预期运行

Do blocks in Haskell not behaving as expected

filterA = [3]
filterB = [2]
output = []

funA n =
if not (elem (n) filterA)
    then do  
        filterA ++ [(3 * n + 2) ] 
        filterB ++ [(3 * n + 2) ]
        output ++ [(3 * n + 2)]
        else output

看来必须养成一些必要的习惯...

这段代码的重点是向filterAfilterBoutput添加一个值,只要n不是相应过滤器列表的一部分(对于此函数,它是 filterA)。已接受的输入被添加到两个过滤器,即使 B 函数(看起来相似)未在此处显示。

我显然误解了 do 的工作方式,因此在这段代码中运行 do 块会返回如下内容:

*Main> funA 4 [14,14,14,14]

我不明白在 do 块中添加到单独的列表是如何混淆的。如何在同一个函数下执行多个操作而不相互干扰?

此外,如果我删除 filterA ++ [(3 ... 行之一,结果变为 [14,14] 并且删除两行会得到所需的结果 [14],当然减去将值连接到 filterAfilterB。但是关于同时拥有它们的一些东西会产生四个重复。

TL:DR 如何在 do 块内执行多​​个单独的操作?不深入monad是否可以理解?是否缺少更简单的解决方案?

追加列表不是一个动作。 filterA ++ [3 * n + 2] 不是一个动作,而是一个表达式。它计算为列表。

您可能想要使用 IO monad。但是你定义的函数的return类型是List,不是IO。在您的定义中,do block 表示列表 monad 而不是 IO monad。

而在Haskell中,一旦定义的值就不能更改。

您可能需要执行以下操作。

funA n = if not (elem n filterA)
        then let
                filterA' = filterA ++ [3 * n + 2]
                filterB' = filterB ++ [3 * n + 2]
                output' = output ++ [3 * n + 2] in
                (filterA', filterB', output')
        else (filterA, filterB, output)