Programmation fonctionnelle

Table of Contents

1. Introduction test

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.

1.2. 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.

1.3. 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'

1.4. Sous expression, sous fonctions

1.4.1. Déclaration where

<expr>
  where
    <decl1>
    <decl2>
    ...

1.4.2. Expression let in

let
    <decl1>
    <decl2>
in <expr>

1.4.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

1.5. 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

1.6. Équivalent des structures de contrôle

1.6.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

1.6.2. Gardes

func a1 a2 ... an
  | <cond1> = <expr1>
  | <cond2> = <expr2>
  | otherwise = <exprDefault>

1.7. Types composés

1.7.1. Tuples

Type (Int, Int) : (1, 1), (4, 2)

Cas particulier ! Type Unit

sertARien :: Int -> ()
sertARien a = ()

1.7.2. Listes

Type [Float], Type[(Int, Char)]...

Fonctions null (vacuité), head tail, mais peu utilisées

1.8. 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)

2. Types

2.1. Type somme

Type offrant une alternative entre plusieus sous-types possibles. Proche d'une enum ou union, ou est un enum en Rust.

2.2. Type produit

Type correspondant au produit cartésien des types qui le composent. Est une struct en C (mais les champs sont nommés).

2.3. Types algébrique

Un type algébrique est à la fois un type somme et un type produit

data Document
    = Ecrit -> Int
    | Audio -> Float, Float
    | Image -> Int, Int

Mais on ne peut pas le print :c Il faut utiliser les dérivations

data Document
    = Ecrit -> Int
    | Audio -> Float, Float
    | Image -> Int, Int
    deriving Show

2.4. Utilisation des types algébriques

Filtrage de motif.

2.5. Type algébrique récursif

Géré par Haskell

data ListeInt
  = Noeud Int ListeInt
  | ListeVide

2.6. Enregistrement

Syntaxe

data T
  = CA
    {
      c1 :: t1,
      c2 :: t2
    }
...

-- Instanciation. Il faut spécifier la valeur de tous les champs

ced = CA
  {
    c1 = ...,
    c2 = ...
  }

Les getters sont des fonctions qui sont le nom des enregistements

c1 CA 2 3 1 ...

3. Fonction d'ordre supérieur

Voir lambda calcul

L'opérateur flèche -> est associative à droite.

Une fonction peut être paramètre d'une autre fonction :

map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = f x : map f xs

3.1. Fonction lambda

On a besoin de littéraux de type fonction, pour éviter de donner des noms de fonctions à chaque fois. Pour cela, Haskell nous fournit une syntaxe pour les fonctions anonymes

-- \ est prononcé lambda
\ p -> <expression> :: tp -> te

3.2. Fonction en résultat de fonctions

Application partielle de fonction renvoie une fonction

4. Ordre supérieur

Author: romann

Created: 2026-10-05 lun. 17:01

Validate