1
votes

I have two functions. The first one gives true if all elements of the list are zero

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

The second function gives true if at least one element of the list is zero

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

Maybe there is another way to solve this problems. For example with map or foldr? Thank you

2
What did you try? Can you implement any and all in terms of foldr? - Willem Van Onsem
@WillemVanOnsem I don't quite understand how foldr works. I understand how map works, but I don't know how to apply it. - Theresa
allZero [] = False is surprising. Are you sure you don't want True in that case, as your informal specification implies? - chi
what the above comment by chi implies is that allZero can be seen as noNonZeros and there are certainly no zeroes in [], so it should return True then. and that's the usual thing to do. - Will Ness
allZero (x:xs) = x == 0 && allZero xs. oneZero (x:xs) = x == 0 || oneZero xs. allZero = all . map (== 0). oneZero = any . map (== 0). all == foldr (&&) True. any == foldr (||) False. <meta> (this is not a full answer as it has no words in it, hence it is left as a comment.) </meta> - Will Ness

2 Answers

1
votes

foldr basically takes your guard as its folding function:

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

acc (for accumulator) is the already-computed value of the recursive call. Being right-associative, the first non-zero value in the list short-circuits the evaluation of the fold function on the rest of the list.

(Note that allZero [] == True by convention. The "hypothesis" is that allZero xs is true, with evidence in the form of a non-zero element to falsify the hypothesis. No elements in the list, no evidence to contradict the hypothesis.)

I leave it as an exercise to adapt this to compute oneZero.

0
votes

foldr function works so:

Suppose, you have list [1, 2, 3]. Let's write this list as (:) 1 ((:) 2 ((:) 3 [])), where each element has type a. Function foldr takes function f of a -> b -> b type and starting element z of b type, and just replace [] to z and : to f. So, foldr f z ((:) 1 ((:) 2 ((:) 3 []))) == f 1 (f 2 (f 3 z)).

So, you can define your functions so:

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

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