vidéo peertube - vidéo youtube - dépôt git
Introduction au langage Haskell
Généralités sur haskell
programmation fonctionnelle : imbrication de fonctions sans effet de bord
intérêts : sûreté, expressivité, optimisation du compilateur
utilisation : compilation, DSL, web backend…
particularités d’Haskell : fonctionnel pur, évaluation paresseuse
quelques liens :
Notions de bases
Quelques définitions
- valeur : donnée de base
- expression : morceau de code pouvant être évalué
- type : ensemble prédéfini de valeurs possibles avec des caractéristiques et opérations particulières
- variable : nom auquel on associe une donnée
Quelques remarques
En Haskell, les variables sont immuables et les expressions respectent la propriété de transparence référentielle
Haskell calcule les types automatiquement mais on peut l’indiquer (pour plus de lisibilité)
Haskell est sensible à l’indentation
les variables et les fonctions commencent par une lettre minuscule
les types et les classes de type commencent par une lettre majuscule
les parenthèses servent à définir des priorités d’évaluation
opérateur d’évaluation
$
commentaire de fin de ligne :
- commentaire multi-ligne :
Types de base
- types simples :
Int
,Float
,String
…
- types composés : tuples, listes
Notion de fonction
- fonction : expression contenant des paramètres; définition/évaluation
-- définit une fonction "ajouter"
ajouter :: Int -> Int -> Int
ajouter x y = x + y
-- évalue la fonction "ajouter" pour les paramètres 10 et 32
x :: Int
x = ajouter 10 32
- fonction anonyme (lambda)
Définir des fonctions par décomposition
if-then-else
: définit une expression en décomposant 2 cas
case
: définit une expression en décomposant plusieurs cas
formaterNombre :: Int -> String
formaterNombre x = case x of
0 -> "zero"
1 -> "un"
otherwise -> "plusieurs"
- pattern matching : définit une fonction selon la valeur des paramètres
formaterNombre :: Int -> String
formaterNombre 0 = "zero"
formaterNombre 1 = "un"
formaterNombre _ = "plusieurs"
- gardes : définit une fonction en testant ses paramètres
formaterNombre' :: Int -> String
formaterNombre' x
| x == 0 = "zero"
| x < 0 = "negatif"
| otherwise = "positif"
Récursivité
- fonction récursive : fonction définie d’après elle-même
factorielle :: Int -> Int
factorielle 1 = 1 -- cas terminal
factorielle x = x * factorielle (x - 1) -- appel récursif
- fonction récursive terminale : l’appel récursif correspond complètement à la dernière expression
factorielle :: Int -> Int
factorielle x = aux 1 x
where aux acc 1 = acc -- fonction auxiliaire récursive terminale
aux acc n = aux (acc*n) (n-1)
Fonction d’ordre supérieur
- définition : fonction qui retourne une fonction
ajouter :: Int -> Int -> Int
ajouter x = \ y -> x + y
-- autre façon de définir :
-- ajouter x y = x + y
- évaluation partielle : évaluation d’une fonction pour une partie des paramètres; produit une fonction
ajouter42 :: Int -> Int
ajouter42 = ajouter 42 -- ici seul le paramètre "x" de la fonction "ajouter" est donné
-- autre façon de définir ajouter42 :
ajouter42 y = ajouter 42 y
- composition de fonctions : définit une fonction en combinant deux autres fonctions
fois2 x = x*2
plus1 x = x+1
fois2plus1 = plus1 . fois2
-- autre façon de définir fois2plus1 :
-- fois2plus1 x = plus1 (fois2 x)
- notation “point-free” : définit une fonction en combinant d’autres fonctions plutôt qu’en exprimant le calcul sur un point du domaine de définition
fois2plus1 x = plus1 (fois2 x) -- calcul sur un point "x" du domaine
fois2plus1 = plus1 . fois2 -- notation point-free
ajouter42 y = ajouter 42 y -- calcul sur un point "y"
ajouter42 = ajouter 42 -- notation point-free
Fonctions sur des listes
- opérateur de construction de liste, par exemple
(:) :: Int -> [Int] -> [Int]
- pattern matching + récursivité
- mapping : applique une fonction sur chaque élément d’une liste
- filtrage : conserve les éléments d’une liste qui vérifient un prédicat
pairs :: [Int] -> [Int]
pairs = filter (\ x -> even x)
-- encore plus concis :
-- pairs = filter even
- réduction : réduit une liste en une valeur en appliquant successivement une fonction sur les éléments
somme :: [Int] -> Int
somme = foldl (\ acc x -> acc + x) 0
-- encore plus concis :
-- somme = foldl (+) 0
Listes en compréhension
- définition de liste combinant génération + filtrage + mapping
Modules
- exemple de définition (fichier
Doubler.hs
) :
- exemple d’utilisation :
Types et classes
Type algébriques
- définir un nouveau type :
- créer des valeurs du nouveau type :
- écrire une fonction avec pattern matching sur les valeurs du type :
calculerSurface :: Forme -> Float
calculerSurface (Carre cote) = cote*cote
calculerSurface (Rectangle longueur largeur) = longueur*largeur
- utilisation de la fonction :
Type paramétrique
- typage paramétrique :
- utilisation :
Classes de type
- indiquer une contrainte de type :
- utilisation avec différents types de la classe :
Classes prédéfinies
classe | fonctions de la classe | types de la classe |
---|---|---|
Eq |
== /= |
Int Float String … |
Show |
show |
Int Float String … |
Num |
+ - * negate abs signum |
Int Float … |
Instances de classe
- implémenter les fonctions d’une classe pour un type :
instance Show Forme where
show (Carre c) = "carre de côté " ++ (show c)
show (Rectangle w h) = "rectangle de longueur " ++ (show w) ++ " et de largeur " ++ show h
- utilisation :
Définir une nouvelle classe
- définir une classe et ses fonctions à implémenter :
- utilisation :
instance Surfacable Forme where
surface = calculerSurface
surfaces :: Surfacable a => [a] -> [Float]
surfaces = map surface
main = do
print $ surfaces [Carre 12, Rectangle 12 3]
Entrées/sorties avec IO
- fonction
main
:
- notation
do
:
- récupérer une entrée :
Monades
design pattern modélisant la notion de séquence et de composition
implémenté par une classe définissant les opérateurs
>>=
(bind),>>
(then) etreturn
la notation
do
un raccourci syntaxiqueexemples de monades :
IO
,Maybe
…