Podem-se definir funções usando listas por compreensão.
Exemplo: A função de ordenação de listas quick sort.
qsort :: (Ord a) => [a] -> [a]
qsort [] = []
qsort (x:xs) = (qsort [y | y<-xs, y<x]) ++[x]++ (qsort [y | y<-xs, y>=x])
<aside> 💡 Esta versão do quick sort faz duas travessias da lista para fazer a sua partição e, por isso, é pior do que a versão anterior com a função auxiliar parte.
</aside>
Exemplo: Usando a função zip e listas por compreensão, podemos definir a função que calcula a lista de posições de um dado valor numa lista.
posicoes :: Eq a => a -> [a] -> [Int]
posicoes x l = [ i | (y,i) <- zip l [0..], x == y]
{- Porquê usar a função Zip :
Exemplo : zip [3,4,5,3,6,3,2] [0..]
[(3,0),(4,1),(5,2),(3,3),(6,4),(3,5),(2,6)] -}
O lado esquerdo do gerador da lista é um padrão.
A lazy evaluation do Haskell faz com que não seja problemático usar uma lista infinita como argumento da função zip.
> posicoes 3 [4,5,3,4,5,6,3,5,3,1]
[2,6,8]
Exemplo: Calcular os divisores de um número positivo.
divisores :: Integer -> [Integer]
divisores n = [ x | x <- [1..n], n `mod` x == 0]
Testar se um número é primo.
primo :: Integer -> Bool
primo n = divisores n == [1,n]
> primo 5
True
> primo 1
False
Lista de números primos até um dado n.
primosAte :: Integer -> [Integer]
primosAte n = [ x | x <- [1..n], primo x]
Lista infinita de números primos.
primos :: [Integer]
primos = [ x | x <- [2..], primo x]