Different Ways to Test if a List Contains Only Positive IntegersΒΆ
The following is a series of Haskell functions that all solve the following problem:
Write a function that takes a list of integers as input, and returnsTrue
if all of them are greater than 0, andFalse
otherwise. The empty list should returnTrue
.
The purpose of this is to get practice with basic Haskell features. Some of these functions are inefficient, or do things in a needlessly tricky way. But that’s okay for now: the point is to try to learn basic Haskell syntax and techniques.
-- equations with if/then/else
all_pos1 :: [Int] -> Bool
all_pos1 [] = True
all_pos1 (x:xs) = if x <= 0 then False else all_pos1 xs
-- guarded equations
all_pos2 :: [Int] -> Bool
all_pos2 [] = True
all_pos2 (x:xs) | x <= 0 = False
| otherwise = all_pos2 xs
-- Remove all numbers >= 0 from the list. If the resulting list is empty, then
-- the numbers were all positive. Otherwise, there are some negatives.
all_pos3 :: [Int] -> Bool
all_pos3 lst = null (filter (<=0) lst)
-- Same idea as all_pos3, but written in a point-free style, i.e. without an
-- explicit name for the input list. The "." is the function compose operator.
all_pos4 :: [Int] -> Bool
all_pos4 = null . (filter (<=0))
-- (all pred lst) is a prelude function that returns True if pred returns true
-- for every element of lst
all_pos5 :: [Int] -> Bool
all_pos5 lst = all (>0) lst
-- Point-free version of all_pos5.
all_pos6 :: [Int] -> Bool
all_pos6 = all (>0)
-- Using a right fold.
all_pos7 :: [Int] -> Bool
all_pos7 lst = foldr (\x y -> x > 0 && y) True lst
-- Using a left fold. Notice that the types of x and y in the folding function
-- have changed.
all_pos8 :: [Int] -> Bool
all_pos8 lst = foldl (\x y -> x && y > 0) True lst
-- Using a list comprehension. This is similar to the "filter" approach above,
-- but with the filter function replaced by a list comprehension.
all_pos9 :: [Int] -> Bool
all_pos9 lst = null [x | x <- lst, x <= 0]
-- Another solution using a list comprehension. The "and lst" functions
-- returns True just when every element of lst evalautes to True.
all_pos10 :: [Int] -> Bool
all_pos10 lst = and [x > 0 | x <- lst]
-- A variation of the previous function that uses map instead of a list
-- comprehension.
all_pos11 :: [Int] -> Bool
all_pos11 lst = and (map (>0) lst)
-- Point-free version of the previous function. "." is function composition.
all_pos12 :: [Int] -> Bool
all_pos12 = and . (map (>0))