diff --git a/labo07/Makefile b/labo07/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..2f11be640726d2d6ccce655fae59c7c357cf05f6
--- /dev/null
+++ b/labo07/Makefile
@@ -0,0 +1,7 @@
+README.html: README.md
+	pandoc -o README.html README.md
+
+.PHONY: clean
+
+clean:
+	rm -f *.html
diff --git a/labo07/README.md b/labo07/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..f202978489cada2135ca137890238990c00d3d1f
--- /dev/null
+++ b/labo07/README.md
@@ -0,0 +1,121 @@
+# Laboratoire 7: Entrées et sorties, révision
+
+## 1 - Entrées et sorties
+
+Écrivez un module Haskell appelé `TrimTrailing.hs` qui prend en entrée
+n'importe quel fichier texte, qui supprime les espaces en fin de ligne (en
+anglais, on les appelle *trailing spaces*) et qui affiche le résultat sur
+`stdout`.
+
+On s'attend donc à ce que la commande
+```haskell
+runhaskell TrimTrailing.hs dirty.txt > clean.txt
+```
+recopie le fichier `dirty.txt` tel quel dans le fichier `clean.txt`, à
+l'exception des espaces superflues qui ont été supprimées.
+
+## 2 - Récursivité
+
+Proposez une implémentation (récursive) des fonctions suivantes (sans faire
+appel à d'autres fonctions, comme `map`, `filter`, etc.):
+```haskell
+-- "Zippe" deux listes
+zip :: [a] -> [b] -> [(a,b)]
+
+-- "Zippe" deux listes en appliquant une fonction
+zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
+
+-- Indique si la première liste est préfixe de la deuxième
+isPrefixOf :: Eq a => [a] -> [a] -> Bool
+```
+
+## 3 - La fonction `iterate`
+
+Une fonction d'ordre supérieur très utile en Haskell est la fonction
+```haskell
+iterate :: (a -> a) -> a -> [a]
+```
+qui applique de façon répétée une fonction à une valeur en stockant le résultat
+dans une liste. Noter que la liste résultante est infinie.
+
+Par exemple, si on souhaite calculer les 10 premières puissances de 3, il
+suffit d'écrire
+```haskell
+>>> take 10 $ iterate (*3) 1
+[1,3,9,27,81,243,729,2187,6561,19683]
+```
+
+## 3.1 - La fonction `iterateWhile`
+
+Donnez l'implémentation d'une fonction
+```haskell
+iterateWhile :: (a -> a -> Bool) -> (a -> a) -> a -> [a]
+```
+qui itère une fonction sur un élément jusqu'à ce qu'une certaine condition soit
+satisfaite.
+
+Par exemple, si nous souhaitons récupérer les puissances de 3 tant que l'écart
+entre deux puissances sucessives est moins de 1000, on écrirait
+```haskell
+>>> iterateWhile (\x y -> y - x < 1000) (*3) 1
+[1,3,9,27,81,243,729]
+```
+
+*Aide*: Une solution possible peut être obtenue en complétant la déclaration
+suivante:
+```haskell
+iterateWhile :: (a -> a -> Bool) -> (a -> a) -> a -> [a]
+iterateWhile f g x
+    | "condition" = une expression qui appelle iterateWhile
+    | otherwise   = le cas de base
+```
+
+## 3.2 - La fonction `iterateUntilEqual`
+
+En utilisant la fonction `iterateWhile` définie plus haut, proposez une fonction
+```haskell
+iterateUntilEqual :: Eq a => (a -> a) -> a -> [a]
+```
+qui a le même comportement que `iterate`, mais qui stoppe l'itération
+lorsqu'une valeur est égale à la suivante dans le résultat.
+
+Par exemple, supposons que nous ayons une fonction qui calcule les différences
+possibles entre toutes les paires d'éléments d'un ensemble:
+```haskell
+allDifferences :: Set Int -> Set Int
+allDifferences s = s `union` fromList [abs (x - y) | x <- elems s, y <- elems s]
+```
+
+Alors on aurait le comportement suivant:
+```haskell
+>>> iterateUntilEqual allDifferences $ fromList [80,5]
+[fromList [5,80],fromList [0,5,75,80],fromList [0,5,70,75,80],fromList [0,5,10,65,70,75,80],fromList [0,5,10,15,55,60,65,70,75,80],fromList [0,5,10,15,20,25,40,45,50,55,60,65,70,75,80],fromList [0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80]]
+>>> last $ iterateUntilEqual allDifferences $ fromList [80,5]
+fromList [0,5,10,15,20,25,30,35,40,45,50,55,60,65,70,75,80]
+```
+Autrement dit, si on prend toutes les différences possibles entre éléments d'un
+ensemble et qu'on répète le processus jusqu'à ce qu'il y ait stagnation (la
+liste obtenue est la même qu'à l'étape précédente), alors on arrête
+l'itération.
+
+Ce patron est fréquent rencontré en informatique: on répète un algorithme
+jusqu'à ce qu'il y ait stagnation. C'est d'ailleurs souvent une condition
+d'arrêt de multiples algorithmes, notamment les algorithmes génétiques.
+
+## 3.3 - La fonction `ancesters`
+
+Récupérez le module [`Simpsons.hs`](Simpsons.hs) disponible dans ce dépôt.
+
+En faisant appel à la fonction `iterateUntilEqual` définie précédemment,
+complétez l'implémentation des fonctions `parents'` et `ancesters`. En
+particulier, on s'attend aux résultats suivants:
+```haskell
+>>> parents' ["Lisa", "Homer"]
+["Homer","Marge","Abraham","Mona"]
+>>> ancesters "Lisa"
+["Homer","Marge","Abraham","Mona","Clancy","Jackie","Orville","Yuma","Willard","Theodora"]
+```
+
+*Note*: Il est possible de définir la fonction `ancesters` sans faire appel à
+la fonction `iterateUntilEqual`, mais il s'agit d'un excellent exercice pour
+voir si vous comprenez bien comment utiliser les fonctions d'ordre supérieur.
diff --git a/labo07/Simpsons.hs b/labo07/Simpsons.hs
new file mode 100644
index 0000000000000000000000000000000000000000..2c461d9960f279a6677fe84acdacb78481717d76
--- /dev/null
+++ b/labo07/Simpsons.hs
@@ -0,0 +1,31 @@
+module Simpsons where
+
+import qualified Data.Map.Strict as Map
+import Data.Set
+
+type Person = String
+
+parents = Map.fromList [("Bart",    ["Homer",   "Marge"]),
+                        ("Lisa",    ["Homer",   "Marge"]),
+                        ("Maggie",  ["Homer",   "Marge"]),
+                        ("Marge",   ["Clancy",  "Jackie"]),
+                        ("Homer",   ["Abraham", "Mona"]),
+                        ("Herb",    ["Abraham"]),
+                        ("Patty",   ["Clancy",  "Jackie"]),
+                        ("Selma",   ["Clancy",  "Jackie"]),
+                        ("Abraham", ["Orville", "Yuma"]),
+                        ("Yuma",    ["Willard", "Theodora"])]
+
+-- | Retourne tous les parents de toutes les personnes données
+parents' :: [Person] -> [Person]
+parents' = error "À compléter"
+
+-- | Retourne tous les ancêtres d'une personne donnée
+--
+-- On dit que x est un ancêtre de y si une des deux conditions suivantes est
+-- respectée:
+--
+-- * x est un parent direct de y
+-- * x est l'ancêtre d'un parent de y
+ancesters :: Person -> [Person]
+ancesters = error "À compléter"