如果列表只有True值,则使用foldl返回True,否则返回false

pig*_*ack 0 haskell

这是我的代码:

boolTrueList :: [Bool] -> Bool
boolTrueList xs
  | length (filterFalse xs) > 0 = False
  | otherwise = True
  where
    filterFalse = filter (==False)
Run Code Online (Sandbox Code Playgroud)

这是完美的工作,但我想用foldr/foldl重写相同的东西,但我被卡住了.

我的想法是折叠一个列表,直到我找到一个假值,然后停止.任何提示?

Dan*_*her 12

我的想法是折叠一个列表,直到我找到一个假值,然后停止.任何提示?

如果你想提早停止,你必须使用foldr.foldl总是必须遍历整个列表(因此在无限列表中根本不起作用).

所以你要

foldr combine default list
Run Code Online (Sandbox Code Playgroud)

default是一个空列表的结果,就在True这里.现在,我们将如何结合?

False遇到a 时,我们想立即返回False,所以

combine False _ = False
Run Code Online (Sandbox Code Playgroud)

当价值是True,我们必须继续,所以

combine True more = more
Run Code Online (Sandbox Code Playgroud)

换句话说combine = (&&),如此

boolTrueList = foldr (&&) True
Run Code Online (Sandbox Code Playgroud)

或者,甚至更短

boolTrueList = and
Run Code Online (Sandbox Code Playgroud)


Ron*_*ell 5

有一种方法可以考虑我发现非常有用和直观的折叠(我可能在某处读过).请注意,这可能无法提供最有效的解决方案,但我在此明确表示关注.

不要将fold视为从列表构建值的函数,而是将其视为在列表元素之间插入运算符的方法.当你这样做时,折叠然后成为一种将列表转换为表达式的方法.例如,以下内容:

foldr op I [A,..,Z]
Run Code Online (Sandbox Code Playgroud)

将产生以下扩展:

A op .. op Z op I 
Run Code Online (Sandbox Code Playgroud)

如果你将这种想法应用到你的问题中,那么你需要做的就是问自己,如果A .. Z是真的,那么我和我应该如何才能得到真的?作为提示,我通常是关于op的标识元素(不改变表达式的值,如0将用于添加).

好吧,我们从逻辑上知道,如果所有操作数都为真,则(&&)只是真的.同样,True是关于&&的标识元素.所以说,你的扩展将是:

A && .. && Z && True
Run Code Online (Sandbox Code Playgroud)

所以你的弃牌是:

foldr (&&) True [A,..,Z]
Run Code Online (Sandbox Code Playgroud)

这意味着你的功能是:

boolTrueList x = foldr (&&) True x
Run Code Online (Sandbox Code Playgroud)

或者更自由的风格:

boolTrueList = foldr (&&) True
Run Code Online (Sandbox Code Playgroud)

使用高阶函数来避免迭代是不够的,我们应该避免迭代思维.考虑开放式表达式而不是"此时此值将传播".通常情况下,迭代只是生成开放式表达式的低级方式,而且由于我们的语言迫使我们这样做,我们的思维方式经常被困在其中,即使我们的语言允许我们思考表达式水平.