Un programme peut-il dire qu'il se trompe avant de s'exécuter ?
Un tableur qui additionne un nom et un nombre donne une réponse étrange, et tu ne le découvres que plus tard. Haskell te demande de dire quel genre de chose chaque fonction reçoit et rend, et vérifie cela avant que rien ne s'exécute. Toute une famille d'erreurs devient alors impossible.
À la fin de cette leçon
Remarque
Je peux lire et exécuter une fonction Haskell et dire ce que m'apprend son type.
Mots clés
- Fonction : quelque chose qui reçoit une valeur et en rend une.
- Type : le genre d'une valeur, comme
Intpour un nombre entier ouStringpour du texte. - Signature de type : la ligne qui donne son type à une fonction, comme
square :: Int -> Int. - Liste : plusieurs valeurs d'un même type, dans l'ordre, écrites
[1, 2, 3]. - Repli (fold) : une façon de combiner tous les éléments d'une liste en une seule valeur.
Pour commencer : ce que tu sais déjà
Remarque
Réponds dans ta tête. 1. En maths, si f(x) = x * x, que vaut f(5) ? 2. 7 est-il le même genre de chose que "seven" ? 3. Quelle est la somme de la liste 1, 2, 3 ? Réponses : 25 ; non, l'un est un nombre et l'autre du texte ; 6.
Avant de commencer
Remarque
Appuie sur Démarrer le lab dans la barre en haut de la leçon et attends qu'il indique qu'il est en marche. Il y a un seul conteneur, haskell. Rien ne s'ouvre dans un navigateur, alors sers-toi du terminal, où docker exec haskell lance une commande à l'intérieur. Le compilateur met quelques secondes à démarrer à chaque fois. Tout ce qui s'affiche est en anglais, quelle que soit la langue de cette page. Chaque bouton Exécuter ci-dessous tape sa commande dans le terminal de ton lab, l'une après l'autre, dans la même session. Pour suivre les commandes ou taper les tiennes, appuie sur Ouvrir le terminal (nouvel onglet) dans la barre.
Une fonction a une signature de type
Cette commande affiche le premier fichier. La ligne square :: Int -> Int est une signature de type. Lis-la ainsi : « square reçoit un Int et rend un Int ». La ligne suivante dit comment : square n = n * n. Ici, une fonction n'a pas d'effet de bord : donne-lui la même valeur et tu obtiens la même réponse. -- commence un commentaire.
docker exec haskell cat Basics.hsAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Exécuter un fichier, ou interroger une fonction
runghc exécute le fichier. Son main affiche trois lignes : Hello, Haskell!, puis 49, puis (True,False). Les options ghc -e calculent une expression avec le fichier chargé : la première demande le type de square et affiche square :: Int -> Int, et la seconde l'appelle et affiche 144.
docker exec haskell runghc Basics.hsAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
docker exec haskell ghc -e ":type square" Basics.hsAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
docker exec haskell ghc -e "square 12" Basics.hsAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Vérifie
Astuce
Que te dit isEven :: Int -> Bool avant même de lire le code ? Réponse : elle reçoit un nombre entier et rend True ou False.
On travaille une liste avec des fonctions
map applique une fonction à chaque élément et filter garde ceux qui réussissent un test. La première commande élève au carré 1 à 5 avec square et les additionne avec sum : elle affiche 55. La seconde garde les nombres pairs de 1 à 10 et affiche [2,4,6,8,10]. Aucune ne modifie la liste d'origine : chacune donne une nouvelle valeur.
docker exec haskell ghc -e "sum (map square [1 .. 5])" Basics.hsAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
docker exec haskell ghc -e "filter even [1 .. 10]"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Une fonction peut s'appeler, et un repli le fait pour toi
mySum dans Fold.hs additionne une liste en ajoutant le premier élément à la somme du reste, et en s'arrêtant à la liste vide. Cette commande affiche 6. La seconde fait le même travail avec le foldr intégré, qui replie une liste en une seule valeur : elle affiche 5050, la somme de 1 à 100.
docker exec haskell ghc -e "mySum [1, 2, 3]" Fold.hsAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
docker exec haskell ghc -e "foldr (+) 0 [1 .. 100]"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Le compilateur vérifie les types
Cette commande donne du texte à square au lieu d'un nombre. Rien ne s'exécute. Le compilateur affiche une erreur qui commence par <interactive> et dit qu'il ne peut pas faire correspondre le type [Char], c'est-à-dire du texte, avec Int. Lis l'erreur depuis le haut : elle nomme la partie fausse de ton expression. Le code entre crochets et la mise en page peuvent changer d'une version à l'autre.
docker exec haskell ghc -e "square \"two\"" Basics.hsAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Une erreur fréquente
Attention
Beaucoup pensent qu'une signature de type n'est qu'un commentaire pour le lecteur. Ce n'est pas le cas. Le compilateur les vérifie toutes, et si le code ne correspond pas, rien ne s'exécute. Écris la signature d'abord quand tu le peux : elle dit ce que tu voulais, et le compilateur te prévient quand le code dit autre chose.
Vérification finale
Astuce
Réponds sans revenir en arrière. 1. Que veut dire Int -> Bool ? 2. Que donne filter even [1 .. 10] ? 3. Quand le compilateur trouve-t-il une erreur de type : avant l'exécution ou après ? 4. Que fait un repli à une liste ? Réponses : reçoit un nombre entier et rend True ou False ; [2,4,6,8,10] ; avant, donc rien ne s'exécute ; il combine tous les éléments en une seule valeur.
Pour les enseignants
Astuce
Cette leçon est un petit exemple de leçon qui se fait dans un lab : les étapes et les boutons Exécuter sont la leçon, et le lab est la copie de chaque élève. Le lab est un conteneur avec le compilateur GHC et quatre petits fichiers, et rien ici ne se corrige tout seul : l'élève rend les expressions qu'il a essayées avec ce que chacune a affiché, une fonction à lui avec son type et un appel qui la montre en marche, et une phrase sur ce qu'une signature de type apprend au lecteur. Points clés : 1. Une fonction reçoit une valeur et en rend une. 2. Une signature de type dit ce qu'une fonction reçoit et rend. 3. On travaille les listes avec des fonctions comme map et filter. 4. Une fonction peut s'appeler elle-même, et un repli fait le même travail. 5. Le compilateur vérifie les types avant que rien ne s'exécute. Erreur fréquente : prendre une signature pour un commentaire. Matériel : le lab et son terminal. Conseil : demandez aux élèves d'écrire le type d'une fonction avant son corps. Chaque réponse est exacte et identique à chaque fois ; la première commande après un démarrage prend quelques secondes. Les noms et les messages sont en anglais, quelle que soit la langue de la page.