type aexp = AEint of int | AEplus of (aexp * aexp) | AEminus of (aexp * aexp) | AEtimes of (aexp * aexp) // funzione di interpretazione let rec aexp_to_string : aexp -> string = fun e -> match e with AEint i -> sprintf "%d" i | AEplus (e,f) -> sprintf "(%s + %s)" (aexp_to_string e) (aexp_to_string f) | AEminus (e,f) -> sprintf "(%s - %s)" (aexp_to_string e) (aexp_to_string f) | AEtimes (e,f) -> sprintf "(%s * %s)" (aexp_to_string e) (aexp_to_string f) (* printfn "%s" (aexp_to_string (AEplus ((AEint 10),(AEint 6)))) *) // semantic domain type eval = int // error handling let negativeError () = failwith "natural numbers should be positive or zero" // denotational semantics let rec sem : aexp -> eval = fun ae -> match ae with AEint i -> if i < 0 then negativeError () else i | AEplus (e,f) -> sem e + sem f | AEminus (e,f) -> sem e - sem f | AEtimes (e,f) -> sem e * sem f (* printfn "%d" (sem (AEplus ((AEint 10),(AEint 6)))) *) let eval_to_string : eval -> string = fun e -> Printf.sprintf "%d" e let eval : aexp -> unit = fun ae -> printfn "%s ==> " (aexp_to_string ae); try printfn "%s\n" (eval_to_string (sem ae)) with Failure message -> printfn "error: %s\n" message printfn "%A" (eval (AEplus ((AEint 10),(AEint 6)))) // parallel computation open System.Threading open System.Threading.Tasks // esempio di funzioni parallele let runTasks () = let rnd = System.Random() for i = 1 to 10 do let t = new Task(fun () -> let time = rnd.Next(3000) Thread.Sleep time printfn "Thread %d waited for %d milliseconds" i time ) t.Start() // il risultato non è deterministico let parallelIncrement () = let a = [| 0 |] for i = 1 to 100 do let t = new Task(fun () -> Thread.Sleep 100 a[0] <- a[0] + 1 printfn "Thread %d done" i ) t.Start() a // usiamo lock per fixare il problema della lettura concorrente // di una cella di memoria da parte di più "thread" let parIncr2 () = let rnd = System.Random() let a = [| 0 |] Array.Parallel.iter (fun i -> lock a (fun () -> let x = a[0] Thread.Sleep (rnd.Next 10) a[0] <- x + 1 printfn "Thread %d done" i ) ) [| 1 .. 1000 |] a printfn "%A" (parIncr2 ()) // però, la lock non risolve problemi con più risorse (i.e. dining philosophers problem)