Programmation fonctionnelle
En Haskell, les fonctions peuvent
Une fonction capable de l’une de ces deux choses est une fonction d’ordre supérieur.
applyTwice qui prend une
fonction f et une valeur x en paramètre, et
applique f à x deux fois de suite :applyTwice f x = f (f x)
Quel est son type ?
combine qui prend en
paramètre une fonction f et un couple (x,y) et
renvoie f x y :combine f (x,y) = f x y
Quel est son type ?
detectZero qui prend en
paramètre une fonction f et un entier x0 et
retourne le plus petit entier x >= x0 tel que
f x vaut 0. Quel est son type ? Définir la
fonction detectZero.λ> f x = if x > 10 then 0 else x
λ> detectZero f 1
11
λ> g x = x `mod` 7
λ> detectZero g 1
7True pour le paramètre. Les fonctions
even et isPrime, par exemple, sont des
prédicats sur les entiers. On veut définir une fonction
numberOf qui prend en paramètre un prédicat et un entier
n et qui compte le nombre d’entiers compris entre
1 et n (inclus) qui vérifient le prédicat.
Quel est son type ? Définir la fonction numberOf.λ> numberOf even 10
5
λ> numberOf isPrime 8
4makeDividePredicate qui
prend en paramètre un entier d et renvoie un prédicat qui
vérifie si un entier n est divisible par d.
Quel est son type ? Définir la fonction
makeDividePredicate. On suppose ici que
d > 0.λ> p = makeDividePredicate 3
λ> p 5
False
λ> p 6
TruePour chaque question, définir la fonction demandée avec son type, en utilisant la récursivité et du pattern matching (bien sûr, vous ne devez pas utiliser directement la fonction équivalente de la bibliothèque standard).
map de Prelude applique une
fonction à chaque élément d’une liste. Définir une fonction
map' ayant le même comportement. La fonction appliquée peut
changer le type des éléments.λ> map' (+1) [1,2,3]
[2,3,4]
λ> map' even [1,2,3,4]
[False,True,False,True]
λ> map' length ["Haskell","est","amusant"]
[7,3,7]filter de Prelude conserve les
éléments d’une liste qui satisfont un prédicat, c’est-à-dire une
fonction qui renvoie un booléen. Définir une fonction
filter' ayant le même comportement. L’ordre des éléments
doit être conservé.λ> filter' even [1,2,3,4,5,6]
[2,4,6]
λ> filter' (>3) [1,5,2,4,3]
[5,4]
λ> filter' (\word -> length word > 3) ["le","chat","dort"]
["chat","dort"]takeWhile de Prelude conserve
les éléments au début d’une liste tant qu’ils satisfont un prédicat.
Elle s’arrête dès le premier élément qui ne le satisfait pas. Définir
une fonction takeWhile' ayant le même comportement.λ> takeWhile' even [2,4,5,6,8]
[2,4]
λ> takeWhile' even [1,2,4]
[]
λ> takeWhile' (<5) [1..]
[1,2,3,4]concatMap de Prelude applique
une fonction à chaque élément d’une liste, puis concatène les listes
obtenues. Définir une fonction concatMap' ayant le même
comportement.λ> concatMap' (\value -> [value,value]) [1,2,3]
[1,1,2,2,3,3]
λ> concatMap' (replicate 3) "abc"
"aaabbbccc"
λ> concatMap' (take 3) [[1..],[10..],[100..],[1000..]]
[1,2,3,10,11,12,100,101,102,1000,1001,1002]isValid qui prend une relation
entre deux éléments et une liste, puis vérifie que cette relation est
satisfaite pour chaque paire d’éléments consécutifs. Une liste vide ou
réduite à un élément est considérée comme valide.λ> isValid (<) [1,3,5,8]
True
λ> isValid (<) [1,3,3,8]
False
λ> isValid (<=) [1,3,3,8]
True
λ> isValid (\first second -> even first /= even second) [1,2,5,8]
TruezipWith de Prelude combine
deux listes élément par élément à l’aide d’une fonction à deux
arguments. Si les listes n’ont pas la même longueur, elle s’arrête
lorsque la plus courte est terminée. Définir une fonction
zipWith' ayant le même comportement.λ> zipWith' (+) [1,2,3] [10,20,30]
[11,22,33]
λ> zipWith' (*) [1,2,3,4] [10,20]
[10,40]
λ> zipWith' (++) ["bon","bon"] ["jour","soir"]
["bonjour","bonsoir"]
λ> zipWith' (,) [1,2,3] "abc"
[(1,'a'),(2,'b'),(3,'c')]partition du module Data.List
sépare une liste en deux listes : la première contient les éléments qui
satisfont un prédicat, la seconde ceux qui ne le satisfont pas. Définir
une fonction partition' ayant le même comportement. L’ordre
des éléments doit être conservé dans chaque liste.λ> partition' even [1,2,3,4,5,6]
([2,4,6],[1,3,5])
λ> partition' (<3) [5,1,3,2,4]
([1,2],[5,3,4])
λ> partition' (\word -> length word > 3) ["le","chat","dort"]
(["chat","dort"],["le"])Pour chaque question, définir la fonction demandée avec son
type, sans récursivité explicite : vous devez uniquement
utiliser les fonctions d’ordre supérieur existantes telles que
map, filter, …, mais sans
utiliser foldr.
deleteAll' qui prend un entier et
une liste d’entiers, puis supprime toutes les occurrences de cet entier.
L’ordre des éléments restants doit être conservé.λ> deleteAll' 2 [1,2,3,2,1]
[1,3,1]
λ> deleteAll' 20 [1,2,3,2,1]
[1,2,3,2,1]
λ> deleteAll' 2 []
[]intersperse du module
Data.List insère un élément entre chaque paire d’éléments
consécutifs d’une liste. Définir une fonction intersperse'
ayant le même comportement, y compris sur la liste vide.λ> intersperse' 0 [1,2,3,4]
[1,0,2,0,3,0,4]
λ> intersperse' ',' "abc"
"a,b,c"
λ> intersperse' 0 [1]
[1]intercalate du module
Data.List insère une liste entre les listes d’une liste de
listes, puis concatène le résultat. Définir une fonction
intercalate' ayant le même comportement, en utilisant
intersperse'.λ> intercalate' [0] [[1,2],[3,4],[5]]
[1,2,0,3,4,0,5]
λ> intercalate' ", " ["Chani","Leto","Duncan"]
"Chani, Leto, Duncan"
λ> intercalate' [0] [[],[1],[]]
[0,1,0]unzip sépare une liste de paires en une
paire de listes : la première contient les premières composantes, la
seconde les secondes composantes. Définir une fonction
unzip' ayant le même comportement.λ> unzip' [(1,'a'),(2,'b'),(3,'c')]
([1,2,3],"abc")
λ> unzip' [("Chani",14),("Leto",12)]
(["Chani","Leto"],[14,12])intersect du module Data.List
conserve les éléments de la première liste qui sont présents dans la
seconde. Définir une fonction intersect' ayant le même
comportement. L’ordre et les occurrences des éléments de la première
liste doivent être conservés.λ> intersect' [1,2,3,4] [5,4,3]
[3,4]
λ> intersect' [1,1,2,2,3,3,4,4] [5,4,3]
[3,3,4,4]isValid' qui prend une relation
entre deux éléments et une liste, puis vérifie que cette relation est
satisfaite pour chaque paire d’éléments consécutifs. Une liste vide ou
réduite à un élément est considérée comme valide.Proposer deux versions :
zipWith ;zip.λ> isValid' (<) [1,3,5,8]
True
λ> isValid' (<) [1,3,3,8]
FalsenubBy du module Data.List
supprime les doublons selon une relation d’équivalence fournie en
argument. Définir une fonction nubBy' ayant le même
comportement : seule la première occurrence de chaque classe
d’équivalence doit être conservée.Pour cette question, la récursivité est autorisée.
Utiliser filter pour retirer les éléments équivalents à
l’élément conservé avant de poursuivre récursivement.
λ> nubBy' (==) [1,2,1,3,2,1]
[1,2,3]
λ> nubBy' (\first second -> first `mod` 3 == second `mod` 3) [0,2,1,5,3,4]
[0,2,1]
λ> nubBy' (\first second -> length first == length second) ["chat","le","dort","ici","un"]
["chat","le","ici"]foldrPour chaque question, définir la fonction demandée avec son
type, en utilisant foldr, sans récursivité
explicite ni appel à la fonction équivalente de la bibliothèque
standard.
Écrire filter'' qui fonctionne comme
filter.
Écrire zipWith'' qui fonctionne comme
zipWith
Écrire concatMap'' qui fonctionne comme
concatMap.