-
Recent Posts
Recent Comments
Archives
Categories
Meta
Tag Archives: f#
Monadi in F#
Giuseppe Maggiore, Ph.D. Student, MSP Universitá Ca’ Foscari – Venezia Consulenze disponibili su F#! Problemi aperti nella programmazione Definire la gestione di eccezioni. Costruire un parser. Accumulare delle informazioni di stato ad ogni riga di una computazione. Definire un sistema … Continue reading
Programmazione funzionale in .Net 3.5: tutorial di base su F# (parte III):
Nota: per poter eseguire questo codice e’ necessario Visual Studio 2008 con installato il Microsoft F# Research Compiler (noi abbiamo usato la versione 1.9.1.3).
Prima di cominciare con il tutorial vero e proprio, e’ importante specificare perche’ questo linguaggio puo’ essere utile. Elenco i vantaggi principali senza entrare nel dettaglio:
questo paradigma e’ perfetto per il multithreading, che entro pochi anni diventera’ semplicemente irrinunciabile (quattro core? otto core? anche di piu’?)
F# e’ strettamente legato a C# e al mondo .Net in generale; si possono scrivere librerie in F# che poi possono essere lette e usate da C# nativamente, nonche’ viceversa
F# puo’ usare qualsiasi libreria .Net (XNA
)
F# genera codice veloce
F# scrive codice logico/matematico semplicemente fantastico
In questo ultimo tutorial introduttivo su F# diamo una impressionante (almeno per noi) dimostrazione di potenza espressiva scrivendo un compilatore/interprete di un semplice linguaggio di espressioni aritmetiche. Mostriamo anche come si possono estendere i costrutti funzionali di F# con costrutti object oriented per esportare classi e altri tipi in un progetto .Net scritto in qualche altro linguaggio (in particolare C#).
Una espressione in questo linguaggio e’ definita come
Le espressioni vengono compilate in listati (liste) di istruzioni in una macchina virtuale basata su stack, dove una istruzione e’:
un tipico esempio di compilazione parte dall’espressione aritmetica originale:
la converte nel linguaggio aritmetico (dove il numero n sottolineato rappresenta Const(n)):
la compila nel listato corrispondente:
e quindi la valuta, ritornando in questo caso il valore 17.
Per costruire questo tutorial dobbiamo definire dei tipi di dato, o unioni discriminate, per rappresentare istruzioni e le espressioni aritmetiche:
type expr = Add of expr * expr | Mul of expr * expr | Div of expr * expr | Sub of expr * expr | Const of int
per cui una variabile di tipo expr sara’ in realta’ una (e una sola) tra Const(int), Add(e1,e2), …
Per trasformare in una lista una espressione possiamo fare pattern matching sul tipo effettivo di una espressione:
let rec ToString e = match e with (Add (e1, e2)) -> “(” + (ToString e1) + ” + ” + (ToString e2) + “)” | (Mul (e1, e2)) -> “(” + (ToString e1) + ” * ” + (ToString e2) + “)” | (Div (e1, e2)) -> “(” + (ToString e1) + ” / ” + (ToString e2) + “)” | (Sub (e1, e2)) -> “(” + (ToString e1) + ” – ” + (ToString e2) + “)” | (Const x) -> x.ToString()
in cui associamo un pezzo di codice da valutare in caso di ogni forma possibile dell’espressione e. Si potrebbero anche avere patterns piu’ complicati, tipo:
(Add (Mul (e1, e2), Div(e3, e4))) -> …
Qui sotto il webcast in cui io e Giulia Costantini mostriamo la stesura di tutto il compilatore/interprete ed infine lo compiliamo in una libreria che apriamo in un progetto C#, per mostrare l’interoperabilita’ tra codice F# e codice in altri linguaggi .Net (download video ad alta risoluzione qui):
[il webcast in streaming richiede silverlight e un attimo di pazienza per il caricamento; in compenso la visione puo' essere effettuata in full-screen a buona risoluzione!] Continue reading
Programmazione funzionale in .Net 3.5: tutorial di base su F# (parte II)
Nota: per poter eseguire questo codice e’ necessario Visual Studio 2008 con installato il Microsoft F# Research Compiler (noi abbiamo usato la versione 1.9.1.3).
Prima di cominciare con il tutorial vero e proprio, e’ importante specificare perche’ questo linguaggio puo’ essere utile. Elenco i vantaggi principali senza entrare nel dettaglio:
questo paradigma e’ perfetto per il multithreading, che entro pochi anni diventera’ semplicemente irrinunciabile (quattro core? otto core? anche di piu’?)
F# e’ strettamente legato a C# e al mondo .Net in generale; si possono scrivere librerie in F# che poi possono essere lette e usate da C# nativamente, nonche’ viceversa
F# puo’ usare qualsiasi libreria .Net (XNA
)
F# genera codice veloce
F# scrive codice logico/matematico semplicemente fantastico
In questo tutorial vedremo come si manipola la struttura dati che la fa da padrone nel mondo ricorsivo di F#: la lista!
Dichiariamo tre liste:
let l1 = [1;2;3;4] let l2 = 1::2::3::4::[] let l3 = l1@l2
l1 contiene i primi 4 interi, l2 anche ma e’ costruita effettuando una serie di operazioni di tipo “push” a partire dalla lista vuota []. Infine l3 e’ la concatenazione delle liste l1 e l2.
Come primo esempio di una funzione che manipola liste vediamo come sommare tutti gli elementi di una lista con una funzione ricorsiva:
let rec sum l = match l with [] -> 0 | x::xs -> x + (sum xs)
in cui vediamo come il pattern matching possa essere usato non solo per ispezionare il valore delle variabili, ma anche la struttura dei loro componenti (ad esempio qui distinguiamo tra la lista vuota [], la somma dei cui elementi e’ 0, e la lista con almeno un elemento x che va sommato alla somma del resto della lista).
Quindi vediamo in opera alcune cosiddette “funzioni di ordine superiore”, ossia funzioni che prendano in input anche altre funzioni per applicarle secondo pattern gia’ noti. Una delle piu’ semplici e’ la funzione di riduzione, ossia:
let rec reduce f l = match l with [] -> failwith “la lista non puo’ essere vuota” | [x] -> x | x::xs -> let acc = reduce f xs in f acc x
in cui la funzione f viene applicata alla riduzione della coda e all’elemento corrente. Se f fosse la funzione che ritorna il massimo tra due valori:
(fun a -> fun b -> if a > b then a else b)
allora reduce ritorna il massimo elemento della lista. Se invece come f usiamo la funzione somma:
(fun a -> fun b -> a + b)
allora reduce ritorna la somma di tutti gli elementi della lista. Esistono moltissimi altri patterns tipici di iterazione di liste e di collezioni, esattamente gli stessi che si trovano in LINQ (ed ecco perche’ abbiamo presentato LINQ come una estensione funzionale di C#, piuttosto che presentarlo come fanno molti come libreria per accesso ai databases).
Qui sotto il webcast tenuto da me (Giuseppe Maggiore) e da Giulia Costantini in cui produciamo questo codice (e molto altro) spiegando in dettaglio cosa significa e mostrando il risultato della sua esecuzione (download ad alta risoluzione qui):
[il webcast in streaming richiede silverlight e un attimo di pazienza per il caricamento; in compenso la visione puo' essere effettuata in full-screen a buona risoluzione!] Continue reading
Programmazione funzionale in .Net 3.5: tutorial di base su F# (parte I)
Nota: per poter eseguire questo codice e’ necessario Visual Studio 2008 con installato il Microsoft F# Research Compiler (noi abbiamo usato la versione 1.9.1.3).
Prima di cominciare con il tutorial vero e proprio, e’ importante specificare perche’ questo linguaggio puo’ essere utile. Elenco i vantaggi principali senza entrare nel dettaglio:
questo paradigma e’ perfetto per il multithreading, che entro pochi anni diventera’ semplicemente irrinunciabile (quattro core? otto core? anche di piu’?)
F# e’ strettamente legato a C# e al mondo .Net in generale; si possono scrivere librerie in F# che poi possono essere lette e usate da C# nativamente, nonche’ viceversa
F# puo’ usare qualsiasi libreria .Net (XNA
)
F# genera codice veloce
F# scrive codice logico/matematico semplicemente fantastico
In questo tutorial vedremo come dichiarare funzioni e costanti in F#. Cominciamo con il dichiarare alcune variabili:
let a = “una stringa” let b = 10 let c = 10.0f let d = ‘a’
con cui dichiariamo una serie di variabili immutabili (quasi delle costanti), lasciando che sia il compilatore a dedurne il tipo. Usiamo la console F# Interactive (integrata in Visual Studio) per farci compilare il codice al volo ed eseguirne pezzi. Vediamo cosa dice la console FSI quando le diamo in pasto il codice appena visto:
val a : string val b : int val c : float32 val d : char
a e’ una stringa, b e’ un intero, c un float e d un char.
Dichiariamo adesso una funzione che somma tre interi tra loro:
let somma x y z = x + y + z
Rispetto al modo “classico” di scrivere una funzione di somma notiamo soprattutto che non esiste la keyword “return” (e’ tutto implicito) e non serve specificare il tipo dei valori da sommare tra loro o il tipo restituito. Rispetto all’equivalente C#, non c’e’ paragone quanto a semplicita’ e velocita’ di scrittura:
int somma(int x, int y, int z) { return x + y + z; }
vediamo ora un semplice esempio di ricorsione (si noti come non scriviamo solo let, bensi let rec per indicare al compilatore che il nome della funzione verra’ usato all’interno della funzione stessa):
let rec fact n = match n with 0 -> 1 | 1 -> 1 | i -> if i < 0 then failwith "fattoriale: solo numeri positivi" else i * (fact (i-1))
in questo snippet vediamo come stiamo facendo cosiddetto "pattern matching" sulla variabile presa in input dalla funzione fattoriale (match n with). Il pattern matching permette di definire una serie di coppie tale che viene ritornato il primo “valore da ritornare” il cui “valore associato” e’ pari al valore della variabile. Sembra magico, ma non lo e’
(ulteriori spiegazioni si trovano nel webcast!).
Qui sotto trovate il webcast (mio -Giuseppe Maggiore- e di Giulia Costantini) in cui viene estensivamente spiegato e mostrato in azione il codice di questo post (download ad alta risoluzione qui):
[il webcast in streaming richiede silverlight e un attimo di pazienza per il caricamento; in compenso la visione puo' essere effettuata in full-screen a buona risoluzione!] Continue reading