On commence par écrire la fonction qui fait le produit de deux
monômes.
let produit_monomes {coeff=c1 ; degre=d1} {coeff=c2 ; degre=d2} = {coeff=c1*c2 ; degre=d1+d2} |
En remarquant que le produit de deux monômes non-nuls est encore un
monôme non-nul, on peut simplement itérer une fois avec
List.map et obtenir le polynôme produit d'un monôme non-nul
et d'un polynôme.
let produit_monome m p = List.map (fun mp -> produit_monome m mp) p |
Voire même en utilisant l'application partielle :
let produit_monome m p = List.map (produit_monomes m) p |
En effet comme l'indique son type monome -> monome -> monome
,
à lire comme monome -> (monome -> monome)
,
la fonction produit_monomes
prend un monôme en argument et
renvoie une fonction qui prend un monome en argument.On termine en itérant encore une fois, à l'aide cette fois
de List.fold_right.
let produit p1 p2 =
List.fold_right
(fun m1 r -> somme (produit_monome m1 p2) r)
p1 [] |
On peut noter que, puisque somme est associative, on peut
ici aussi employer List.fold_left.
let produit p1 p2 =
List.fold_left
(fun r m1 -> somme (produit_monome m1 p2) r)
[] p1 |
Culture
Alors fold_right ou fold_left ?
En ce qui me concerne, je me contente de me souvenir que l'on peut
facilement copier une liste avec fold_right et facilement
inverser une liste avec fold_left.
let copy l = List.fold_right (fun x r -> x::r) l []
let rev l = List.fold_left (fun r x -> x::r) [] l |
Il y a une certaine logique dans tout ça et notamment dans l'ordre des
arguments. En cas de choix possible (opération associative et
commutative par exemple), la préférence va plutôt à
fold_left qui est récursive terminale.