Éléments de syntaxe d'Ocaml

Version & licenses
Creative Commons License

Un peu de syntaxe de base

Guyslain Naves

Manipulations de bases

  1. (* Définition une liste est soit vide, soit un élément suivi d'une liste *)
  2. type 'a list =
  3. | []
  4. | (::) of 'a * 'a list

:: est l'insertion en tête (gauche) de liste. On ne peut pas l'utiliser pour ajouter un élément à la fin (droite) de la liste. Les listes se manipulent uniquement depuis la gauche. Accèder à la droite demander de parcourir toute la liste, ce qui a une complexité linéaire par rapport au nombre d'éléments.

La définition des listes est inductive : elles se manipulent donc naturellement avec la combinaison récursion-filtrage par motif.

  1. let rec my_function list = match list with
  2. | [] -> ...
  3. | first::others -> ...
  4. (* first : 1er élément, others : liste des autres éléments *)

  5. (* D'autres motifs sont possibles dans le match : *)
  6. | [single_elt] -> (* liste à un seul élément *)
  7. | first::second::others -> (* avec 2 éléments ou plus *)
  8. | [one;two;three] -> (* liste à 3 éléments exactement *)
  9. | ...

Principales fonctionnelles

Le triumvirat qui règne sur les listes :

  1. (* map transforme une liste en une liste de même taille *)
  2. List.map f [e1;e2;e3;...;ek] ---> [f e1; f e2; f e3; ...; f ek]

  3. (* filter garde les éléments qui vérifie une propriété *)
  4. (* en utilisant une notation mathématique (<> Ocaml) *)
  5. List.filter predicat [e1;e2;e3;...ek] ---> [ei | predicat ei]

  6. (* fold_left calcule une valeur en utilisant tous les éléments d'une liste *)
  7. List.fold_left (++) neutral [e1;e2;...;ek]
  8. ---> (...((neutral ++ e1) ++ e2 ) ...) ++ ek

Pour compléter :

  1. (* flatten aplatit une liste de listes en liste *)
  2. flatten [[a_1;...a_k];[b_1;...;k_l];...]
  3. ---> [a_1;a_2;...;a_k;b_1;b_2;...;b_l;c_1;...]

  4. (* pour chainer des opérations, définir : *)
  5. let rec bind list ~f =
  6. list
  7. |> List.map f
  8. |> List.flatten
  9. let (>>=) list f = bind list ~f
  10. (* bind : 'elt list -> ~f:('elt -> 'im list) -> 'im list *)

  11. (* Exemple : construire toutes les paires d'éléments de deux listes : *)
  12. let product list1 list2 =
  13. list1 >>= fun elt1 -> (* pour tout elt1 dans list1 *)
  14. list2 >>= fun elt2 -> (* pour tout elt2 dans list2 *)
  15. [(elt1,elt2)] (* construire la paire (elt1,elt2) *)

  16. let res = product [1;2;3] [4;5]
  17. (* res = [(1,4);(1,5);(2,4);(2,5);(3,4);(3,5)] *)

Tester une liste

  1. (* Test d'appartenance *)
  2. List.mem elt [e1;e2;...;ek]
  3. ---> elt = e1 || elt = e2 || ... || elt = ek

  4. (* Test de la validité de tous les éléments *)
  5. List.for_all predicat [e1;e2;...;ek]
  6. ---> predicat e1 && predicat e2 && ... && predicat ek

  7. (* Test de l'existence d'un élément valide *)
  8. List.exists predicat [e1;e2;...;ek]
  9. ---> predicat e1 || predicat e2 || ... || predicat ek
  10. (* on peut utiliser List.find pour obtenir le premier élément valide *)

Autres fonctions très utiles

  1. (* La longueur d'une liste *)
  2. List.length [a1;a2;...ak] ---> k

  3. (* La fonction de tri en ordre ascendant. *)
  4. List.sort compare_op unsorted_list ---> sorted_list
  5. (* compare_op : 'elt -> 'elt -> int, compare_op a b est comme a - b *)

  6. (* Coupler deux listes de même longueur *)
  7. List.combine [a1;a2;...;ak] [b1;b2;...;bk]
  8. ---> [(a1,b1);(a2,b2);...(ak,bk)]

  9. (* L'opération inverse de combine *)
  10. List.split [(a1,b1);(a2,b2);...(ak,bk)]
  11. ---> ([a1;a2;...;ak],[b1;b2;...;bk])