Programmation fonctionnelle
Table of Contents
1. Introduction
1.1. Effets de bords
Le soucis des fonctions du paradigme impératif, c'est qu'on peut avoir des changements des paramètre dans d'autres fonctions. C'est ce que les fonctions pures règlent : la fonction renvoie toujours le même résultat. Haskell est un langage fonctionnel pur, càd qu'il n'a que des fonctions pures. C'est un langage strict (bonne nouvelle !). Il faut un peu se battre avec le compilateur, mais il est un bon garde-fous : si le code compile, alors il y a de fortes chances que le code soit correct.
2. Haskell
2.1. Les expressions
prenons la fonction polynôme \(f(x) = ax^{2}+bx+c\)
En python, on l'écrirait :
def poly(a, b, c, x):
x1 = a*x*x
x2 = b*x
return x1 + x2 + c
En haskell, c'est :
poly a b c x = a*x*x + b*x + c
Il n'y a aucune instruction, que des expressions.
Opérateur de typage : `::`. Par exemple :
(3+6)::Float
Et interdiction de faire `(3::Float) + (5::Int)`, c'est vraiment pas bien et le compilateur sera bougon.
2.2. Les fonctions
La fonction `doubler`
doubler :: Integer -> Integer -- Typage de doubler doubler x = 2*x -- Définition de doubler
La fonction `estMajuscule`
estMajuscule :: Char -> Bool estMajuscule c = 'A' <= c && c <= 'Z'
2.3. Sous expression, sous fonctions
2.3.1. Déclaration where
<expr>
where
<decl1>
<decl2>
...
2.3.2. Expression let in
let
<decl1>
<decl2>
in <expr>
2.3.3. Exemple : différence de gaussiennes
dog :: Float -> Float -> Float -> Float -> Float
dog x y si so = g so - g si
where
g s = norm/s*exp (coords/s)
norm = 1 / (2*pi)
pi = 3.14159
coords = x*x + y*y
2.4. Opérateurs binaires
test :: Integer -> Integer -> (Integer -> Integer -> Integer) -> Integer test a b f = f a b test 3 5 + -- 8 test 3 5 * -- 15
Pour définir des opérateurs infixes, on écrit :
(+*) :: Int -> Int -> Int (+*) a b = 2* (a+b) 1 +* 2 doubleSomme :: Int -> Int -> Int a `doubleSomme` b = 2* (a+b) doubleSomme 2 3 2 `doubleSomme` 3
2.5. Équivalent des structures de contrôle
2.5.1. Conditionnelle
En python :
def va(x):
res = x
if x < 0:
res = -x
return res
En Haskell
va :: Int -> Int va a -> if a < 0 then -a else a
2.5.2. Gardes
func a1 a2 ... an | <cond1> = <expr1> | <cond2> = <expr2> | otherwise = <exprDefault>
2.6. Types composés
2.6.1. Tuples
Type (Int, Int) : (1, 1), (4, 2)
Cas particulier ! Type `Unit`
sertARien :: Int -> () sertARien a = ()
2.6.2. Listes
Type [Float], Type[(Int, Char)]...
Fonctions `null` (vacuité), `head` `tail`, mais peu utilisées
2.7. Filtrage de motif
Exemple :
incrementTuple :: (Bool, Int, Int) -> (Bool, Int, Int) incrementTuple t = ... ? -- Comment faire des opérations en fonction du bool ? -- On fait : incrementTuple t = case t of (True, n1, n2) -> (True, n1, n1+n2) (False, n1, n2) -> (False, n2, n1)