List Comprehensions
x <- [1..5]
: generators
- Comprehensions can have multiple generators, and the order matters
- Variable of later generators changes more frequently (more nested)
- Can use
let
declarations
> [(x, y) | x <- [1, 2, 3], y <- [4, 5]]
[(1, 4), (1, 5), (2, 4), (2, 5), (3, 4), (3, 5)]
> [(x, y) | y <- [4, 5], x <- [1, 2, 3]]
[(1, 4), (2, 4), (3, 4), (1, 5), (2, 5), (3, 5)]
Dependent Generator
- Later generators can depend on variables introduced by earlier generators.
> [(x, y) | x <- [1..3], y <- [x..3]]
[(1, 1), (1, 2), (1, 3), (2, 2), (2, 3), (3, 3)]
concat :: [[a]] <- [a]
concat xss = [x | xs <- xss, x <- xs]
Gaurd
- Restrict values produced by earlier generators.
> [x | x <- [1..10], even x]
[2, 4, 6, 8, 10]
factors :: Int -> [Int]
factors n = [x | x <- [1..n], n `mod` x == 0]
prime :: Int -> Bool
prime n = factors n == [1, n]
Zip
- Maps two lists to a list of pairs of their corresponding elements
pairs :: [a] -> [(a, a)]
pairs xs = zip xs (tail xs)
sorted :: Ord a => [a] -> Bool
sorted xs =
and [x <= y | (x, y) <- pairs xs]
positions :: Eq a => a -> [a] -> [Int]
positions x xs = [i | (e, i) <- zip xs [0..length xs-1], e == x]
String Comprehension
count :: Char -> String -> Int
count x xs = length [ c | c <- xs, c == x ]