如何在不重命名变量的情况下累积更改?

pap*_*uck 3 haskell

我有一个字符串列表,errors。我做了一些检查,如果有任何失败,我会在后面附加一条消息errors。像这样:

let errors = []
let errors' = errors ++ if (check1 fails) then ["check1 failed"] else []
let errors'' = errors' ++  if (check2 fails) then ["check2 failed"] else []
Run Code Online (Sandbox Code Playgroud)

当然,还有一种更惯用的方式来累积更改,errors而不必每次都生成新变量。我需要Data.IORef突显可变变量吗?似乎过分杀伤力。

如果仅删除撇号,则编译器将返回错误,因为它陷入了无限循环。

cut*_*lus 7

您可以将条件和消息分组在一起

checksTodo = [(check1 fails, "check1 failed"), (check2 fails, "check2 failed")]

errors = map snd (filter fst checksTodo)
Run Code Online (Sandbox Code Playgroud)

如果您愿意使用列表理解语法,则可以改用更易读的方式编写它:

errors = [ msg | (cond, msg) <- checksTodo, cond ]
Run Code Online (Sandbox Code Playgroud)

如果仅删除撇号,则编译器将返回错误,因为它陷入了无限循环。

发生这种情况是因为let默认情况下,Haskell中的绑定(不同于大多数语言)是递归的。这意味着如果你说

let errors = errors ++ if (check1 fails) then ["check1 failed"] else []
Run Code Online (Sandbox Code Playgroud)

编译器会将其视为递归定义。当您尝试errors在运行时求值时,您需要errors进行计算进入无限循环errors