lazy lists

OCAML Lazy Lists: Prime numbers

Submitted by fabio on Sat, 2007-12-08 15:01.

An algorithm implemented in OCAML to create a list of prime numbers using lazy lists.

Sorry for the code comments in Italian. Please add a comment below if you don't get parts of the algorithms.

(* Varesano Fabio - Liste LAZY *)

(* FUNZIONI PER L'USO DI LISTE LAZY *)

exception EmptyArg;;

(* Definizione del TIPO llist per le liste lazy *)
type 'a llist = Lnull| Lcons of (unit -> ('a * 'a llist));;

(* funzione che mi restituisce il PRIMO ELEMENTO della lista lazy
*  lhd : 'a llist -> 'a = 
*)
let lhd= function Lnull -> raise EmptyArg | Lcons(y) -> fst(y ());;

(* funzione che mi restituisce una lista lazy che contiene il resto della lista passata come argomento
*  tranne il primo elemento
*  ltl : 'a llist -> 'a llist = 
*)
let ltl= function Lnull -> raise EmptyArg| Lcons(y) -> snd(y ());;

(* funzione che AGGIUNGE in testa un elemento ad una lista lazy *)
let lcons a ll  =   Lcons (function () ->(a, ll));;

(* funzione che definisce una lista lazy a partire da un intero n
 *  lfrom: int -> int llist
*)
let rec lfrom n = Lcons(function () -> (n,(lfrom (n+1))));;

(* funzione che prende i primi n elementi di una lista lazy passata come argomento e restituisce una lista lazy
*  ltake: int -> 'a llist -> 'a llist
*)
let rec ltake (n, ll) = match (n,ll) with
			(0,_) -> Lnull
			|(n, Lnull) -> Lnull
			|(n,Lcons(y)) -> let y1= y () in lcons (fst y1) (ltake(n-1, snd(y ())));;

(* funzione che trasforma una lista lazy in una lista
* llist2list : 'a llist -> 'a list
*)
let rec llist2list= function 
			Lnull -> []
    			| Lcons(y) -> let y1= y () in (fst y1)::llist2list (snd (y ()));;



(* FUNZIONI PER IL CALCOLO DEI NUMERI PRIMI *)

(* funzione che, data una lista, elimina i multipli di n, seguendo l'ordine di inserimento nella lista
* Il calcolo si ferma al raggiungimento di radice(n)
*)
let rec leliminaMultipli n= function 
					Lnull -> Lnull
					|Lcons(y) -> let y1=y () in let first= fst y1 and tail = snd y1 
							 in if first mod n = 0 then (leliminaMultipli n tail) 
							 else Lcons(function () -> (first, leliminaMultipli n tail));;

(*funzione che effettua il CRIVELLO di eratostene per il calcolo dei numeri primi 
*)
let rec lcrivello = function 
		    Lnull -> Lnull 
		    |Lcons(y) -> let y1=(y ()) in let first=fst y1 
		    in Lcons(function() -> (first, lcrivello(leliminaMultipli first (snd y1))));;

(* funzione che restituisce la lista dei primi n NUMERI PRIMI calcolati col metodo di Eratostene*)
let primes = function
		  0 -> Lnull
		  | n -> ltake(n, lcrivello (lfrom 2));;