type complex = {im: float; re: float};;

let zc = {re=0.;im=0.};;

let addc = fun {im=a; re=b} {im=c; re=d} -> {im=a+.c; re=b+.d};;

( Types sommes )

( constructeurs constants )

type colors = Blue | Red | Green;;

let perm = function Blue -> Red | Red -> Green | Green -> Blue;;

( constructeurs avec parametres )

type num = Entier of int | Flottant of float;;

let addnum = function (Entier a, Entier b) -> Entier (a+b) | (Entier a, Flottant b) -> Flottant (float a+.b);;

type intlist = Nil | Cons of int * intlist;;

( listes d'entiers )

let rec append = function (Nil,l) -> l | (Cons(a,r), l) -> Cons(a, append (r,l));;

( pouvoir des types recursifs: un programme qui diverge )

type d = Plie of (d->d);;

let plie = fun f -> Plie f;; let deplie = fun (Plie f) -> f;;

let delta = (deplie x) x;;

let boom = delta (plie delta);; ( tapez ctrl-c ! )

( types POLYMORPHES: listes et operations sur listes )

type 'a list = Nil | Cons of 'a * 'a list;;

let rec append = function (Nil,l) -> l | (Cons(a,r), l) -> Cons(a, append (r,l));;

let rec list_hom f e = function Nil -> e | Cons(a,l) -> f a (list_hom f e l);;

( exemples de homomorphismes )

let length = list_hom (fun x y -> y+1) 0;;

let reverse = list_hom (fun x y -> append (y,(Cons(x,Nil)))) Nil;;

let filter p = list_hom (fun x l -> if p x then Cons(x,l) else l) Nil;;

( les listes sont aussi predefinies!!! )

open List;;

[];;

1::[];;

[1];;

[1;2;3;4];;

let rec list_hom f e = function [] -> e | a::l -> f a (list_hom f e l);;

let filter p = list_hom (fun x l -> if p x then x::l else l) [];;

( on peut aussi l'ecrire directement : )

let rec filter p = function [] -> [] | (a::r) -> if p a then a::(filter p r) else (filter p r);;

filter (fun x -> x mod 2 =0) [1;2;3;4;5;6];;

( les TRI sur les listes )

( quicksort )

let rec partition p = function [] -> [],[] | (a::r) -> let (l1,l2) = partition p r in if p a then ((a::l1),l2) else (l1,(a::l2));;

partition (fun x -> x mod 2 =0) [1;2;3;4;5;6];;

let rec qsort cmp = function [] -> [] | (a::r) -> let (p,g) = partition (fun x -> cmp a x) r in (qsort cmp p)@[a]@(qsort cmp g);;

qsort (fun x y -> x < y) [1;4;3;2;9;5;10];;

qsort (fun x y -> x > y) [1;4;3;2;9;5;10];;

( mergesort )

let rec partition_merge = function [] -> [],[] | [a] -> [a],[] | (a::(b::r)) -> let (l1,l2) = partition_merge r in (a::l1),(b::l2);;

partition_merge [1;2;3;4;5;6;7;8;9];;

let rec merge cmp = function (a::r,b::s) -> if cmp a b then a::(merge cmp (r, (b::s))) else b::(merge cmp ((a::r), s)) | ([],l) -> l | (l,[]) -> l;;

let rec mergesort cmp = function [] -> [] | [a] -> [a] ( necessaire pour la terminaison ) | l -> let (l1,l2) = partition_merge l in merge cmp (mergesort cmp l1, mergesort cmp l2);;

mergesort (fun x y -> x > y) [1;4;3;2;9;5;10];; mergesort (fun x y -> x < y) [1;4;3;2;9;5;10];;

( les arbres binaires )

type 'a arbre = Empty | Node of 'a arbre 'a'a arbre;;

( parcours d'arbre )

let rec infixe = function Empty -> [] | (Node(ag,i,ad)) -> (infixe ag)@[i]@(infixe ad);;

let rec prefixe = function Empty -> [] | (Node(ag,i,ad)) -> [i]@(prefixe ag)@(prefixe ad);;

let rec postfixe = function Empty -> [] | (Node(ag,i,ad)) -> (postfixe ag)@(postfixe ad)@[i];;

( homomorphismes )

let rec hom_tree f e = function Empty -> e | (Node(ag,i,ad)) -> f (hom_tree f e ag) i (hom_tree f e ad);;

( exemples )

let maptree f = hom_tree (fun g i d -> Node(g,f i,d)) Empty;;

maptree (fun x -> x+1) (Node(Node(Empty,3,Empty),4,Node(Empty,5,Empty)));;

let hauteur = hom_tree (fun g i d -> 1+(max g d)) 0;;

hauteur (Node(Node(Empty,3,Empty),4,Node(Empty,5,Empty)));;

let taille = hom_tree (fun g i d -> 1+g+d) 0;;

taille (Node(Node(Empty,3,Empty),4,Node(Empty,5,Empty)));;

let miroir = hom_tree (fun g i d -> Node(d,i,g)) Empty;;

miroir (Node(Node(Empty,3,Empty),4,Node(Empty,5,Empty)));;

( parcours infixe generalises, pliages )

let rec plie_droite f e = function Empty -> e | (Node(g,i,d)) -> plie_droite f (f (plie_droite f e g) i) d;;

let infixe a = plie_droite (fun l x -> x::l) [] a;;

infixe (Node(Node(Empty,3,Empty),4,Node(Empty,5,Empty)));;