(* Cours numero 4: les aspets imperatifs et le systeme de modules*)
(* les exceptions *)
(* un type somme ouvert *)
exception Liste_zero;;
let multlist_eff l =
let rec aux = function [] -> 1
| (a::r) -> if a=0 then raise Liste_zero
else a*(aux r)
in try aux l with Liste_zero -> 0;;
(* vecteurs *)
let v = [|"a"|];;
(* acces de 0 a n-1 *)
v.(0);;
(* affectation *)
v.(0)<- "aa";;
v.(0);;
(* enregistrements avec champs modifiables *)
type point = {mutable x:int};;
let movepoint p dx = p.x<-p.x+dx;;
(* les cases memoire *)
type 'a ref = {mutable info: 'a};;
let refval {info=v} = v;;
let setref v r = r.info<-v;;
(* ce type predefini pour comodite, avec !r pour refval r et r:=v pour setref v r *)
(* un neud d'une liste avec "pointeurs" explicites *)
type 'a cell = {info: 'a; mutable next: 'a cell};;
(* exemple: liste circulaires *)
(* on utilise les noeuds ... *)
let make_cl v = let rec c = {info=v;next=c}
in c;;
let hd {info=v;next=l} = l.info;;
let tl {next=rest} = rest;;
let insert_hd v cl = let el = {info=v;next=cl.next}
in cl.next<-el; cl;;
let insert_tl v cl = let el = {info=v;next=cl.next}
in cl.next<-el; el;;
let remove_hd cl = cl.next<- cl.next.next; cl;;
(* mais cela ne marche que sur le liste non vides: *)
(* on va faire mieux ... *)
type 'a circ_list = Nil | List of 'a cell;;
(* il nous faut traiter les cas exceptionnels: *)
(* on definit des exceptions aussi *)
let insert_head v = function Nil -> List (make_cl v)
| (List cl) -> List (insert_hd v cl);;
let insert_tail v = function Nil -> List (make_cl v)
| List cl -> List (insert_tl v cl);;
exception Remove_Empty_cl;;
let remove_head = function Nil -> raise Remove_Empty_cl
| List cl -> let v =hd cl
in let l= if cl.next==cl.next.next then Nil
else List (remove_hd cl)
in (v,l);;
(* cela est suffisant pour definir un type de donnee pile avec *)
(* insertion et suppression en temps constant *)
(* Les Modules *)
(* terminologie de l'algebre: les modules sont comme des algebres: *)
(* ils ont une sig(nature), sont des struc(tures), et on les transforme *)
(* avec des foncteurs *)
module type File =
sig
exception FileVide
type 'a file
val mkempty: unit -> 'a file
val enqueue: 'a -> 'a file -> 'a file
val dequeue: 'a file -> 'a * 'a file
val isempty: 'a file -> bool
end;;
module FileCLPasProtege =
struct
type 'a cell = {info: 'a; mutable next: 'a cell}
let make_cl v = let rec c = {info=v;next=c} in c
let hd {info=v;next=l} = l.info
let insert_tl v cl = let el = {info=v;next=cl.next}
in cl.next<-el; el
let remove_hd cl = cl.next<- cl.next.next; cl
type 'a circ_list = Nil | List of 'a cell
let insert_tail v = function Nil -> List (make_cl v)
| List cl -> List (insert_tl v cl)
exception Remove_Empty_cl
let remove_head = function Nil -> raise Remove_Empty_cl
| List cl -> let v =hd cl
in let l= if cl.next==cl.next.next then Nil
else List (remove_hd cl)
in (v,l)
(* attention aux pieges avec les effets de bord: si on ecrit *)
(* (hd cl, if .. then .. else ... remove_hd cl ..) *)
(* il peut arriver que remove_hd soit execute avant hd!!! *)
exception FileVide
type 'a file = 'a circ_list
let mkempty () = Nil
let enqueue v l = insert_tail v l
let dequeue l = try remove_head l with Remove_Empty_cl -> raise FileVide
let isempty = function Nil -> true | _ -> false
end;;
(* si on veut faire propre, on peut restraindre la signature *)
module FileCL = (FileCLPasProtege : File);;
FileCL.enqueue;;
(* Une autre structure de file: meme cout amortit, mais fonctionnelle *)
module FileDL : File =
struct
type 'a file = 'a list * 'a list
exception FileVide
let mkempty () = [],[]
let enqueue v (l1,l2) = (l1,v::l2)
let dequeue = function (a::r,l) -> a,(r,l)
| ([], []) -> raise FileVide
| ([], l) -> let (a::l') = List.rev l in (a,(l',[]))
let isempty = function ([],[]) -> true
| _ -> false
end;;
type 'a arbre = Empty | Node of 'a arbre * 'a * 'a arbre
module ParcLarg =
functor (F:File) ->
struct
let rec bf f p = if F.isempty f then List.rev p
else let (a,f') = F.dequeue f
in match a with
Empty -> bf f' p
| Node(g,v,d) -> bf (F.enqueue d (F.enqueue g f')) (v::p)
let parclarg a = bf (F.enqueue a (F.mkempty())) []
end;;
let b=
Node
(Node (Node (Empty, 4, Empty), 2, Node (Empty, 5, Empty)), 1,
Node (Node (Empty, 6, Empty), 3, Node (Empty, 7, Empty)));;
(* et maintenant, testons le tout! *)
module PCL = ParcLarg(FileCL);;
PCL.parclarg b;;
module PDL = ParcLarg(FileDL);;
PDL.parclarg b;;