Lab Haskell : programmation fonctionnelle avec fonctions et types, dans le navigateur
Ce lab donne à chaque élève un compilateur Haskell à lui, avec quatre petits fichiers à lire, exécuter et modifier : fonctions et types, listes, repliements et récursivité, et un type à eux. Un programme Haskell est fait de fonctions qui reçoivent des valeurs et en rendent, et chaque fonction a un type que le compilateur vérifie avant que rien ne s’exécute.
Ce n’est pas un lab d’attaque. Chaque copie n’a aucune route vers internet ni vers un autre élève : rien ne peut y être téléchargé et rien de ce qui s’y trouve ne peut atteindre quelqu’un d’autre. Il n’a que le compilateur et les bibliothèques qui l’accompagnent : aucun paquet supplémentaire ne peut être installé, donc ni cabal install ni stack.
Ce que les élèves apprennent
Qu’un programme peut être construit avec des fonctions, et qu’un type dit ce que chacune reçoit et rend. Les élèves lisent une signature de type, exécutent un fichier, calculent une expression, appliquent map et filter à une liste, écrivent une fonction qui s’appelle elle-même et voient un repliement faire le même travail, puis rencontrent une erreur de type qui arrête un programme avant son exécution. Un quatrième fichier ajoute un type à eux à deux formes, avec une fonction qui le démonte en regardant de quelle forme il s’agit. Ce lab convient à une introduction aux paradigmes de programmation ; vérifiez le libellé exact dans l’unité de votre propre organisme, aucun n’est cité ici.
Le lancer dans votre navigateur
Le lab démarre un service, haskell, à partir de l’image officielle haskell, sous un compte sans privilèges. Il n’y a pas de page web : la barre du lab n’a donc aucun lien sous « Dans votre navigateur », et c’est le terminal qui sert à exécuter du code. Il atteint le compilateur avec docker exec haskell, suivi de runghc et d’un nom de fichier pour exécuter un fichier, ou de ghc -e et d’une expression entre guillemets pour calculer une expression. Le compilateur met quelques secondes à démarrer à chaque fois. Chaque réponse est identique à chaque fois, et tout ce qui s’affiche est en anglais, quelle que soit la langue de la page.
Pour discuter avec le compilateur, appuyez sur « Ouvrir le terminal » et tapez docker exec -it haskell ghci Lists.hs. À l’invite ghci> tapez une expression et appuyez sur Entrée, comme map (* 2) [1, 2, 3], qui affiche [2,4,6]. Tapez :t suivi d’un nom pour voir son type, et :quit pour quitter.
- Ouvrir la page Conteneur. Ouvrez « Créer » dans la barre et choisissez « Lancer un conteneur ». Tout le monde peut ouvrir la page, et le lab Git et le lab SQL se lancent sans compte. Tous les autres labs demandent un compte gratuit : créez-en un, connectez-vous, puis appuyez sur « Démarrer ».
- Trouver le lab. La carte « Laboratoires d’exemple » liste tous les exemples. Trouvez Haskell : fonctions, types et listes.
- Appuyer sur Démarrer. « Démarrer » le lance tel quel, en un clic. « Modifier le fichier d’abord » ouvre le fichier compose pour que vous puissiez le changer avant de démarrer.
- L’ouvrir. Il n’y a pas de page web à ouvrir. Sur la page du lab, appuyez sur « Ouvrir le terminal » et tapez docker exec haskell runghc Basics.hs pour exécuter le premier fichier : il affiche Hello, Haskell!, puis 49, puis (True,False).
Que demander aux élèves de rendre
Les expressions qu’ils ont essayées et ce que chacune a affiché : une qui appelle une fonction d’un fichier, une qui applique map ou filter à une liste, et une qui fait signaler une erreur de type par le compilateur. Puis une fonction à eux ajoutée à Basics.hs avec sa signature de type et un appel qui la montre en marche, et une phrase ou deux, dans leurs mots, sur ce qu’une signature de type apprend au lecteur. Rien n’est noté automatiquement : la fonction et la phrase montrent si c’était compris. Pour un travail plus poussé, demandez d’écrire la signature d’abord et de dire ce qu’elle promet.
Une leçon de base sur ce lab
Haskell Basics est une petite leçon qui se fait dans ce lab. L’élève y lit une fonction et son type, exécute un fichier, applique une fonction à une liste, replie une liste et rencontre une erreur de type.
Un compte personnel gratuit la reçoit dans le module Basics, qui se trouve sur « Accueil », et chaque établissement peut la copier depuis le dossier Basics de la Bibliothèque. Elle est volontairement petite : elle montre à un enseignant ce qu’est une leçon qui se fait dans un lab, et le lab fait le reste. Copiez-la dans un module à vous pour la modifier.
Le code sur GitHub
Le fichier compose n’a pas de Dockerfile : il lance une seule image publique officielle, Haskell avec GHC, figée sur la version 9.10.1, sous un compte sans privilèges avec 384 Mo de mémoire. GHC est le gourmand : exécuter un fichier, une expression seule, l’invite interactive et une compilation complète d’un fichier comme ceux-ci a atteint près de 250 Mo en comptant le cache des fichiers du compilateur, et le même travail s’est terminé dans 192 Mo ; 384 Mo laissent donc de la marge. L’image et le compilateur ont des licences libres permissives et ne sont pas distribués par nous. Le fichier écrit quatre petits fichiers d’exercice au premier démarrage et les garde sur un volume : ce que l’élève change est donc encore là après un arrêt et un démarrage. Les limites sont honnêtes : il n’y a aucune sortie, donc aucun paquet supplémentaire, et un très gros programme peut demander plus de mémoire que le lab n’en a.
En faire un travail
Indiquez dans la tâche ce qu’il faut rendre.
- Créer le lab. Dans votre module, ajoutez une tâche et choisissez la carte « Lab de conteneurs », puis « Dans un dépôt GitHub ». Indiquez https://github.com/mitsurutech/lab-haskell-lab avec la branche main. Le fichier compose par défaut est compose.yaml. Faites d’abord un fork du dépôt si vous voulez le modifier, par exemple pour d’ajouter d’autres fonctions aux fichiers de départ.
- Publier et l’essayer. « Publier » fige le commit qui vous a été montré : un changement ultérieur dans le dépôt ne modifie donc pas un lab que vous avez déjà proposé. Démarrez d’abord votre propre copie.
- Le distribuer. Attribuez-le comme n’importe quelle tâche, avec une échéance si vous le souhaitez, et indiquez dans la tâche ce qu’il faut faire et ce qu’il faut rendre.
- Noter ce qui est rendu. Ouvrez la copie d’un élève et le travail rendu, notez-le et renvoyez-le avec un motif s’il demande un complément.
Essayer ce lab, et ce qu’il coûte
Un compte personnel gratuit permet de suivre les leçons de base de ce lab, avec chaque mois assez de crédit gratuit pour suivre la plupart des leçons, sans carte. Pour une classe, un établissement a ses 365 premiers jours gratuits pour 50 élèves au plus, puis paie par élève et par an, tous les labs compris et les enseignants gratuits.
Questions fréquentes
- Pourquoi la première commande est-elle lente ?
- Le compilateur doit démarrer et lire ses bibliothèques à chaque fois, ce qui prend quelques secondes. Exécuter un fichier avec runghc ou une expression avec ghc -e le fait à chaque fois. Pour beaucoup d’essais à la suite, utilisez l’invite interactive, ghci, qui ne démarre qu’une fois.
- Pourquoi les noms et les messages restent-ils en anglais sur une page dans une autre langue ?
- Le message d’accueil des fichiers, les mots Just et Nothing et tous les messages du compilateur sont en anglais, et le lab ne les change pas. La leçon le dit et explique chaque réponse dans la langue de la page.
- Les élèves peuvent-ils installer un paquet ?
- Non. Le lab n’a aucune sortie vers internet : rien ne peut être téléchargé, seules les bibliothèques fournies avec le compilateur sont là. Tout ce qui vient de ces bibliothèques, comme Data.Char, peut être importé.