List comprehensions provide a concise way to create lists in Haskell. They are inspired by set notation in mathematics and allow for the construction of lists using existing lists, applying functions, and filtering elements.

Key Concepts

  1. Basic Syntax:

    • The general form of a list comprehension is [expression | qualifier1, qualifier2, ...].
    • expression is the output function.
    • qualifiers are either generators (which produce values) or guards (which filter values).
  2. Generators:

    • Generators are of the form pattern <- list.
    • They produce elements from the list and bind them to the pattern.
  3. Guards:

    • Guards are boolean expressions that filter the elements produced by the generators.
    • Only elements for which the guard evaluates to True are included in the output list.

Practical Examples

Example 1: Simple List Comprehension

-- Generate a list of squares of numbers from 1 to 10
squares = [x * x | x <- [1..10]]

Explanation:

  • x <- [1..10] is a generator that produces numbers from 1 to 10.
  • x * x is the expression that computes the square of each number.

Example 2: List Comprehension with Guards

-- Generate a list of even numbers from 1 to 20
evens = [x | x <- [1..20], x `mod` 2 == 0]

Explanation:

  • x <- [1..20] is a generator that produces numbers from 1 to 20.
  • x mod 2 == 0 is a guard that filters out odd numbers.

Example 3: Multiple Generators

-- Generate a list of all possible pairs (x, y) where x is from 1 to 3 and y is from 4 to 6
pairs = [(x, y) | x <- [1..3], y <- [4..6]]

Explanation:

  • x <- [1..3] and y <- [4..6] are generators that produce all combinations of x and y.

Example 4: Nested List Comprehensions

-- Generate a list of lists, where each sublist contains numbers from 1 to n
nestedLists = [[1..n] | n <- [1..5]]

Explanation:

  • n <- [1..5] is a generator that produces numbers from 1 to 5.
  • [1..n] is the expression that generates a list from 1 to n for each n.

Exercises

Exercise 1: Generate a List of Cubes

Task: Write a list comprehension to generate a list of cubes of numbers from 1 to 10.

cubes = [x^3 | x <- [1..10]]

Exercise 2: Filter Multiples of 3

Task: Write a list comprehension to generate a list of numbers from 1 to 30 that are multiples of 3.

multiplesOf3 = [x | x <- [1..30], x `mod` 3 == 0]

Exercise 3: Cartesian Product

Task: Write a list comprehension to generate the Cartesian product of two lists [1, 2, 3] and [4, 5, 6].

cartesianProduct = [(x, y) | x <- [1, 2, 3], y <- [4, 5, 6]]

Exercise 4: Pythagorean Triples

Task: Write a list comprehension to generate all Pythagorean triples (a, b, c) such that a, b, and c are integers between 1 and 20.

pythagoreanTriples = [(a, b, c) | a <- [1..20], b <- [1..20], c <- [1..20], a^2 + b^2 == c^2]

Common Mistakes and Tips

  • Forgetting Guards: Ensure that guards are used correctly to filter out unwanted elements.
  • Nested Generators: Be careful with the order of generators, as it affects the resulting list.
  • Complex Expressions: Break down complex expressions into simpler parts to avoid confusion.

Conclusion

List comprehensions are a powerful feature in Haskell that allow for the concise and readable construction of lists. By understanding the syntax and practicing with various examples, you can leverage list comprehensions to write more efficient and elegant Haskell code. In the next module, we will delve into the type system of Haskell, starting with type inference.

© Copyright 2024. All rights reserved