5. Cos’è la FP? (Prima interpretazione)
Un paradigma di programmazione secondo il quale le funzioni hanno un
ruolo hanno un ruolo primario (first class citizen)
Il primo linguaggio ad utilizzare fortemente le funzioni è stato il FORTRAN
II
5
6. Cos’è la FP? (Prima interpretazione)
Il discorso diventa interessante quando le funzioni diventano gli attori
principali in un linguaggio
Ad esempio, prendere una funzione e passarla come parametro o
conservarla in una variabile o far ritornare ad una funzione un’altra
funzione
Higher Order Functions
Lexical Closure. Ogni funzione ha accesso alle variabili esistenti in una
funzione esterna. Da Scheme, questa caratteristica è arrivata oggi ad
essere una delle qualità migliori del linguaggio più mainstream del 2016:
Javascript
06/09/2
016
SalvatoreSorrentino-Coursera
Challenge
6
7. Cos’è la FP? (Seconda interpretazione)
Programmazione Funzionale Pura
Le funzioni vanno intese nel senso di funzioni matematiche
Concetto abbastanza diverso dall’interpretazione precedente
Poiché l’ultima volta che abbiamo visto una definizione formale di funzione
matematica è stato n anni fa ( con n a vostra scelta…), ricordiamola
brevemente
06/09/2
016
SalvatoreSorrentino-Coursera
Challenge
7
8. Definizione formale di funzione 8
Assegnato x, non esiste nessun effetto che possa cambiare il valore f(x)
9. Argomenti a favore della FP pura
Tutto diventa più semplice e sicuro. Non esistono effetti collaterali che
possano far nascere bug
Se qualcosa funziona, lo farà per sempre.
Ok, tutto molto bello ma…che sono questi effetti collaterali?
9
11. Lavorare con le date è un side-effect
Il risultato dell’applicazione di DateTime.Now() varrà una sola volta e ogni
successiva chiamata produrrà un valore diverso
DateTime.Now non è una funzione matematica
Beh se non posso nemmeno farci IO a che ca..volo serve un linguaggio
funzionale puro?E’ solo non-sense accademico
Usiamo solo i linguaggi imparativi
11
16. Eccezioni
Le eccezioni sono così potenti che possono essere usate per simulare
qualsiasi tipo di side-effect (Mark LilliBridge – Unchecked Exceptions can
be strictly more powerful than call/CC)
16
28. Commenti all’Angular tutorial
La funzione non ha argomenti. Quando ciò accade, una delle due seguenti
affermazioni deve essere vera:
La funzione deve restituire la stessa cosa ogni volta perché non c'è nulla che
possa differenziare l'output.
ci sono side-cause nascoste, ossia un input magico che la funzione non dichiara
che serve a produrre un output differente.
28
30. Commenti sull’Angular Tutorial
Questa funzione, oltre a non avere argomenti, non ritorna nulla. Che senso
ha invocare una funzione che non ritorna nulla? Nessuno, a meno che la
funzione non abbia dei side-effect nascosti
30
31. I Side-Effect sono un iceberg di complessità 31
La signature della funzione ci offre una vaga idea di quello che può succedere invocandola ma non ci
protegge da tutti i possibili effetti collaterali.
La funzione potrebbe dipendere da uno o più input nascosti; potrebbe avere uno o più output
nascosti (ad esempio scrivere su database, rimuovere righe da tabelle di un database, cancellare
tabelle, etc!)
33. I SIDE-EFFECT DISTRUGGONO I COMPONENTI
06/09/2
016
SalvatoreSorrentino-Coursera
Challenge
33
Perché in loro presenza non esiste più il concetto di isolamento
34. I SIDE-EFFECT DISTRUGGONO LA COMPOSIZIONE
06/09/2
016
SalvatoreSorrentino-Coursera
Challenge
34
Things cannot plugged together.
35. Rendiamo un linguaggio puro
Ok, vogliamo rendere il nostro linguaggio di programmazione preferito
privo di effetti collaterali. Cosa dobbiamo fare?
Basta eliminare un po’ di roba: le assegnazioni, i loop (usiamo la
ricorsione), le Date e le funzioni Random
A questo punto scopriremo di avere tra le mani un linguaggio che non
serve a nulla perché i programmi che scriviamo non fanno calcoli puri ma
interagiscono col mondo; un mondo che evolve continuamente. Se i nostri
programmi non sono in grado di seguire l’evoluzione del mondo allora
siamo fregati
35
36. La crisi di Haskell
Haskell era un linguaggio di programmazione funzionale puro affascinante
e brillante. Tuttavia era impossibile usarlo in applicazioni reali
Poi i suoi adepti scoprirono un trucco. C’era una scappatoia negli contratti
che definivano una funzione: una funzione può prendere un’altra funzione
come parametro. Ogni volta che una funzione viene chiamata passando
un’altra funzione come parametro, essa sarà differente perché ogni
funzione è qualcosa di unico, chiuso rispetto a ciò che l’ha creata.
Possiamo quindi evadere dall’obbligo di dovere essere privi di side-effect.
Cosa??
36
37. Interludio 2: Monoid
Definiamo un po’ di notazioni f: int -> int
Estendiamola a qualsiasi tipo a f: a -> a
Aggiungiamo una seconda funzione g: a-> a
Vogliamo combinare le due funzioni. L’intuizione ci dice che possiamo
farlo perché entrambe vanno a-> a
Definiamo un operatore di combinazione ° (f °g) a = f (g a)
La composizione è qualcosa che ti aiuta a gestire la complessità di un
problema: partendo da blocchi costitutivi semplici che ben conosciamo,
arriviamo a costruire nuovi blocchi più complessi
37
38. Interludio 2 : Monoid 38
Un monoide è una collezione di cose, più una regola per combinare
queste cose e questa regola obbedisce a due altre regole
I numeri su un orologio formano un monoide. La regola di
composizione è (x+y) %12. Ad esempio, 7 + 10 = 5
La regola di composizione obbedisce a due regole:
1) Associatività x ° ( y ° z) = (x °y) °z
2) Deve esistere un elemento u tale che x ° u = x e u ° x = x
Nell’esempio dell’orologio, u = 12
N.B. La regola di composizione non è commutativa!
39. Interludio 2: Monoid
Tornando alla prima slide sui monoid, le funzioni sotto composizione
formano un Monoid ( se ovviamente i tipi coincidono)
f ° g = h: a -> a
Lasciamo la dimostrazione all’attento lettore
39
40. Monad
Partiamo da un monoide di funzioni del tipo f: a -> a e modifichiamo leggermente le
definizioni
x: a
f : a -> Ma
g: a -> Ma
h: a -> Ma
Dove M è una trasformazione applicata ad un tipo a. La funzione f applicata ad a ritorna un
qualcosa di più, un extra dato applicato ad a
M deve essere lo stesso per le 3 funzioni
Non sappiamo che cosa faccia Ma e che tipo sia. Non dobbiamo specificarlo! Potremmo stare
eseguendo query su database, gestire IO, concorrenza, etc etc. In generale avremo un side-
effect arbitrario
Si può dimostrare che esiste ancora la composizione delle funzioni
L’idea è portare il mondo dei side-effect sotto controllo mediante la composizione in un
monoid.
40
41. Monad in Haskell
In Haskell una lambda expression si scrive a -> ….
In Haskell si definisce l’operatore bind >>= per indicare la composizione
delle Monad functions
La composizione assume la seguente terrificante forma
41
42. Monads: perché??
Abbiamo bisogno della camposizione delle funzioni per gestire la
complessità. La composizione deve tenere conto dei side effect
L’operatore bind va costruito per ogni tipo di Monad che vogliamo
realizzare. La comunità Haskell creò la I/O monad che gli dava la possibilità
di scrivere codice come se il linguaggio prevedesse I/O anche se ciò non
era vero. Da un punto di vista pratica, la I/O monad rendeva il loro codice
compilabile.
Va costruita anche la funzione unit per dimostrare che si tratta di un vero
monoid. Tipicamente in Haskell la funzione unit si chiama return: f-> Ma
Perché ci hai fatto vedere queste cose orrende?? Non le useremo mai in
vita nostra!!!
42
43. Language Integrated Query (LINQ) 43
LINQ extends the language by the addition of
query expressions, which are akin to SQL statements, and
can be used to conveniently extract and process data
from arrays,enumerable classes, XMLdocuments, relational
databases, and third-party data sources.
LINQ è una monade.
Nel mondo di LINQ,
• M a è IEnumerable<a>
• >>= è SelectMany o Select
public static IEnumerable<B> SelectMany<A, B>(this IEnumerable<A> first, Func<A, IEnumerable<B>> selector)
public static IEnumerable<TResult> Select<TSource, TResult>( this IEnumerable<TSource> source, Func<TSource, TResult> selector )
46. Monads: ancora una piccola cosa…
La composizione vale anche in un caso più generale
f: a -> Mb
g: b -> Mc
f°g = a-> Mc
46
47. Monads
Secondo gli esperti, per capire le monadi bisogna imparare prima Haskell e
la Category Theory.
E’ un po’ come dire che per capire la parmigiana di melenzare, devi
imparare la lingua napoletana
Possiamo fare un bel po’ di cose con la parmigiana di melenzane senza
dover conoscere necessariamente il napoletano: possiamo ordinarla al
ristorante, possiamo mangiarla, possiamo gustarne il sapore, possiamo
persino imparare a prepararla.
Ciò non ci impedisce, se lo desideriamo, di imparare il Napoletano e
Haskell
47
48. Monads in Javascript ( D. Crockford)
Javascript va benissimo perché utilizza il concetto di higher order functions
e questo ci basta
Ci bastano un po’ di funzioni
function unit (value) che ritorna una monade
function bind(monad, function(value)) che prende una monade e una
function che prende un value e ritorna una monade
Nel caso di Javascript la monade è in generale un oggetto)
48
49. Monads in Javascript (D. Crockford)
Partiamo dalla funzione unit. Se prende un argomento e ritorna un
oggetto, quindi deve essere un costruttore! Nulla di magico!
Quindi la magia deve essere nella funzione bind
Per arrivare a scrivere qualcosa di concreto, ci servono tre assiomi la cui
comprensione lasceremo agli studiosi lettori
Assioma 1: bind(unit(value), f) === f(value)
Assioma 2: bind(monad, unit) === monad
Assioma 3: bind(bind(monad,f),g) === bind(monad, function(value) {
return bind(f(value),g)}
49
50. Monads in Javascript ( D. Crockford)
Può essere utile convertire le espressioni dalla notazione funzionale nella
notazione con un metodo
bind(monac, func)
monad.bind(func)
Gli assiomi che abbiamo esposto prima diventano
unit(value).bind(f) === f(value)
monad.bind(unit) === monad
monad.bind(f).bind(g) === monad.bind(function(value){
return f(value).bind(g);
Ma a cosa servirà mai una cosa del genere? Non la userò mai!!
Ho un oggetto, chiamo un metodo su questo oggetto, prendo il risultato e
invoco un altro metodo. Vi ricorda qualcosa?
50
51. Ajax Monad (D.Crockford)
Per anni abbiamo usato questo modello senza sapere che si trattava di una
monade
monad.bind(f).bind(g)
Ad esempio:
var ajax = MONAD()
.lift(‘alert’, alert);
var monad = ajax(«Hello»);
monad.alert();
51
53. La Monad identity (Douglas Crockford) 53
La identity monad ci serve a definire
il costruttore identity.
Invochiamo il costruttore identity
passandogli la stringa «Hello
World»
Infine, invochiamo il metodo bind
della Monad passandogli la
funzione alert di Javascript
54. Un po’ di storia (Brian Beckman)
Negli anni in cui nacque la teoria informatica (tra il 1947 e il 1950), si
scontrarono subito due correnti di pensiero
Bottom-Up : si parte dall’hardware, aggiungiamo astrazioni di cui abbiamo
bisogno per avvicinarci alla teoria matematica ma mai a prezzo delle
performance (Fortran, C, C++, Java, C#)
Top-Down: partiamo dalla matematica e sottraiamo astrazioni per arrivare
in basso alle macchine anche a spese delle performance (Lambda calculus,
Algol, Lisp, Smalltalk, ML, Haskell)
La confluenza delle due linee di pensiero si trova in linguaggi come F# e
Scala
54
55. Tanto, alla fine, C# avrà tutte le feature di F#, vero?
Prima di rilasciare F#, Don Syme è stato protagonista nel portare generics
in C# e nel framework .NET Non fosse stato per lui, C# sarebbe ancora
tristemente simile a Java.
F# ha introdotto gli async workflow nel 2007. C# ha introdotto async/await
nel 2012
C#6 ha introdotto tante piccole feature ancora poco note, gran parte delle
quali già esistenti da tempo in F#
Per C#7, il team ha deciso davvero di esagerare nel processo di
assimilazione delle feature di F#: pattern matching, records, immutability,
tuples
La risposta alla domanda nel titolo è: non proprio…
55
57. C# Non avrà mai…
Mancano ancora diverse feature di F# in C# ma pare ragionevole che
possano essere aggiunte: Pattern Matching, No Nulls, Discriminated
Unions (venite ai meetup di F# per imparare cosa sono!)
A detta degli autori di F#, C# non potrà mai avere i Type Provider e le
Unità di misura
Ma soprattutto, il compilatore F# non consente le circular dependencies.
Non potete usare un tipo o una funzione prima di averla definita. Portare
questa richiesta in C# sarebbe un breaking change nel compilatore. Gran
parte del codice scritto finora in C# non compilerebbe più. Vi lascio un link
https://fsharpforfunandprofit.com/posts/cycles-and-modularity-in-the-
wild/ dove si parla di quest’argomento («Entity Framework has the most
cycles, involving 24% of the classes»)
57
62. Functional Program Design in Scala
For Expressions and Monads
Lazy Evaluation
Functions and State
Timely Effects (lezioni di Erik Meijer)
62
63. Parallel Programming
Running Computations in Parallel
Basic Task Parallel Algorithms
Data-Parallelism
Data Structures for Parallel Computing
63