使用map和foldr实现函数,haskell

问题描述

我有两个功能。如果列表的所有元素都为零,则第一个返回 true

allZero :: [Int] -> Bool
allZero [] = False
allZero [0] = True
allZero (x:xs)
  | x == 0 && allZero xs = True
  |otherwise = False

如果列表中至少有一个元素为零,则第二个函数返回 true

oneZero :: [Int] -> Bool
oneZero [] = False
oneZero (x:xs)
   | x == 0 = True
   | otherwise = oneZero xs

也许有另一种方法可以解决这个问题。例如使用地图或文件夹? 谢谢

解决方法

foldr 基本上把你的守卫作为它的折叠功能:

allZero = foldr (\x acc -> x == 0 && acc) True

acc(用于 accumulator)是递归调用的已计算值。由于是右结合,列表中的第一个非零值会使列表其余部分的折叠函数的计算短路。

(注意 allZero [] == True 按照惯例。“假设”是 allZero xs 为真,有非零元素形式的证据来证伪假设。列表中没有元素,没有证据与假设相矛盾。)

我把它留作练习来调整它以计算 oneZero

,

foldr 函数是这样工作的:

假设您有列表 [1,2,3]。让我们将此列表写为 (:) 1 ((:) 2 ((:) 3 [])),其中每个元素的类型为 a。函数foldr采用f类型的函数a -> b -> bz类型的起始元素b,只需将[]替换为z:f。所以,foldr f z ((:) 1 ((:) 2 ((:) 3 []))) == f 1 (f 2 (f 3 z))

所以,你可以这样定义你的函数:

allZero = foldr (\x -> x == 0 &&) True

oneZero = foldr (\x -> x == 0 ||) False