Secondo esempio spiegato.

Per ragionare meglio sul secondo esempio, lo riscriviamo scomponendo l’espressione che determina il valore di tipo Picture.

import Graphics.Gloss
f y = Rotate (2*y) . Translate 0 y $ Circle y
ps = [f y | y <- [5,10 .. 100]]
main = displayInWindow "secondo esempio" (500,600) (0,0) white $ Pictures ps

Per caricare questa definizione in ghci, si deve salvare il codice in un file “esempio2.hs”, aprire ghci e usare il comando :load

Prelude> :load esempio2
[1 of 1] Compiling Main             ( esempio2.hs, interpreted )
Ok, modules loaded: Main.
*Main> 

Ora possiamo interrogare l’interprete per conoscere i tipi dei nomi caricati

*Main> :t f
f :: Float -> Picture
*Main> :t ps
ps :: [Picture]

Il tipo di f è lo stesso di Circle. Infatti il significato dell’espressione è: un cerchio di raggio y , spostato di y pixel in alto e ruotato intorno all’origine di 2*y gradi. Quindi una funzione che da qualsiasi y di tipo Float crea una Picture.
Andiamo piano. Prima di tutto eliminiamo il . e l’$ che sono combinatori e ci complicano la vita all’inizio. Utilizziamo le parentesi per isolare le sottoespressioni.

f y = Rotate (2*y) (Translate 0 y (Circle y))

L’espressione è equivalente ma meno idiomatica. Osseviamo i tipi dei 3 costruttori in gioco.

*Main> :t Circle
Circle :: Float -> Picture
*Main> :t Translate
Translate :: Float -> Float -> Picture -> Picture
*Main> :t Rotate
Rotate :: Float -> Picture -> Picture
*Main> 

C’è qualcosa che distingue nettamente Circle dagli altri. Infatti Circle è l’unico che pare costruisca una Picture, gli altri la trasformano. Ma in haskell le cose non si trasformano, le cose si creano e basta. Allora si capiscono meglio i tipi di Translate e Rotate. Translate vuole i due spiazzamenti orizzontale e verticale e una Picture, così facendo esso è un’altra Picture. Stesso vale per Rotate che vuole un angolo ed una Picture, risultando in una nuova Picture.

Questa corrispondenza tra la descrizione e il codice è la forza dei datatype ricorsivi: essi sono un buon modello per un linguaggio descrittivo.
I datatype ricorsivi contengono valori del tipo che stanno defininendo nella definizione dei propri costruttori.
Dobbiamo capire che essi sono semplicemente un valore, come 42 o “primo esempio” o 12.34, ma descrivono un valore che ha una struttura complessa.
Scriviamo alcuni valori di tipo Picture.

*Main> :t Translate 10 10 (Circle 10)
Translate 10 10 (Circle 10) :: Picture
*Main> :t Rotate 40 (Circle 20)
Rotate 40 (Circle 20) :: Picture
*Main> :t Translate 10 10 (Rotate 40 (Circle 20))
Translate 10 10 (Rotate 40 (Circle 20)) :: Picture
*Main> 

Il secondo ostacolo è il valore ps.

ps :: [Picture]

Il suo tipo si legge “Lista di valori di tipo Picture”. Purtroppo la lista è il primo tipo parametrico che incontriamo, ed ha una sintassi un po speciale che confonde molto le idee. Una lista è un tipo ricorsivo esattamente come Picture, ma è polimorfo, ovvero è di tipo diverso a seconda del tipo degli elementi che contiene.
Questa cosa riflette il suo significato, una lista di numeri è diversa da una lista di lettere, diversa da una lista di Picture e così via. Siccome la lista è omni presente nel codice haskell, una sintassi speciale è stata introdotta, in particolare il suo tipo si scrive [] e il suo parametro, il tipo degli elementi che contiene si scrive all’interno delle quadre. Anche il costruttore di valori lista si scrive [] e l’elenco dei valori contenuti si mette dentro separato da virgole.

*Main> :t ['a','b','c','d']
['a','b','c','d'] :: [Char]

Questa era una lista di caratteri. Il suo tipo [Char] si può scrivere [] Char. Il valore è stato costruito con parentesi quadre e elementi separati da virgole.
Nell’esempio ho usato una sintassi speciale per le liste (e non solo) che si chiama list comprehension e un operatore anch’esso speciale che genera sequenze dati gli estremi.
Vediamo prima l’operatore .

Prelude> :t ['a' .. 'z']
['a' .. 'z'] :: [Char]
Prelude> [1 .. 10]
[1,2,3,4,5,6,7,8,9,10]
Prelude> [1,3 .. 10]
[1,3,5,7,9]
Prelude> [10,8 .. -10]
[10,8,6,4,2,0,-2,-4,-6,-8,-10]
Prelude> 

E ora la list comprehension.

Prelude> [x * 2 | x <- [1..10]]
[2,4,6,8,10,12,14,16,18,20]

L’operazione costruisce una lista moltiplicando per 2 tutti gli elementi di [1 .. 10]. Prima della barra verticale scriviamo l’espressione che descrive un elemento della lista, dopo la barra descriviamo l’assegnazione degli elementi ai nomi che appaiono nell’espressione.
Nell’esempio sopra x * 2 impone che un elemento è il doppio del valore del nome x. Mentre x <- [1 .. 10] impone che il nome x assuma i valori da 1 a 10 nell’espressione dell’elemento.


Prelude> [(x,y) | x <- ['a' .. 'c'], y <- [1 .. 3]]
[('a',1),('a',2),('a',3),('b',1),('b',2),('b',3),('c',1),('c',2),('c',3)]

Qui creiamo delle coppie dette tuple. Da notare che gli assegnamenti alla ‘x’ e alla ‘y’ non avvengono in parallelo , ma ogni elemento della ‘x’ viene accoppiato con ogni elemento ‘y’.

Tornando a ps, ps è una lista di elementi creati applicando la funzione ‘f’ ad ogni ‘y’ dove ‘y’ varia tra 5 e 100 con passo 5. Ma la funzione ‘f’ genera una Picture da un Float, quindi i valori assegnati a ‘y’ sono Float e ps è una lista di Picture.

Possiamo vedere i primi valori di ps che sono i cerchi che compongono la nostra figura.

*Main> take 3 ps
[Rotate 10.0 (Translate 0.0 5.0 (Circle 5.0)),Rotate 20.0 (Translate 0.0 10.0 (Circle 10.0)),Rotate 30.0 (Translate 0.0 15.0 (Circle 15.0))]

Per finire esaminiamo il costruttore Pictures, infatti l’ultimo argomento di displayInWindow deve essere di tipo Picture, mentre ps è di tipo [Picture].

*Main> :t Pictures
Pictures :: [Picture] -> Picture
*Main> :t ps
ps :: [Picture]
*Main> :t Pictures ps
Pictures ps :: Picture

Esattamente il necessario per accontentare displayInWindow.

Installare haskell su ubuntu 11.10

Ghc è il compilatore haskell più diffuso tra i programmatori funzionali.

Per tutti è disponibile la platform che è aggiornata al compilatore 7.0.3.

Su ubuntu si installa da terminale con:

sudo apt-get install haskell-platform
cabal update

Come supporto non necessario allo sviluppo c’è un IDE

sudo apt-get install leksah

Solitamente questo basta a programmare in haskell.

Per i più esigenti, si può installare l’ultima versione del compilatore, la 7.2.1.

Prima di tutto assicurare la presenza di gmp.

sudo apt-get install libgmp3c2 libgmp-dev

Scaricare e aprire il tarball corretto per l’architettura

http://www.haskell.org/ghc/download_ghc_7_2_1

Configurare e installare dalla cartella scompattata

./configure
sudo make install

Per finire serve cabal install. Indispensabile è la libreria  zlib.

sudo apt-get install zlib1g-dev

Controllare la presenza di git.

sudo apt-get install git

Clonare la versione modificata di cabal install

git clone https://github.com/tuncer/cabal-install.git

Spostarsi nella cartella clonata

cd cabal-install

Effettuare l’inizializzazione del database pacchetti

sh ./bootstrap.sh

Ora l’eseguibile cabal si trova nelle cartelle sotto ~/.cabal. E’ buona norma aggiungere  la cartella ~/.cabal/bin alla variabile di environment PATH

echo "PATH=$PATH:~/.cabal/bin" >> ~/.bashrc

Per ricaricare il file modificato

source ~/.bashrc

Infine l’aggiornamento iniziale dell’indice pacchetti presente su hackage

cabal update

Prima lezione IPT

Perché l’informatica è bella.

Cos’è il computer.

Il computer in italiano si chiama calcolatore perché fa sempre un sacco di calcoli.

Quindi il calcolatore è pieno zeppo di numeri e passa tutto il tempo a fare delle operazioni tra i numeri che stanno li.

Ma i numeri nel calcolatore non sono proprio tutti uguali. A seconda del posto che occupano possono significare cose diverse. Ecco quindi spiegato come mai il calcolatore sembra fare molte più cose che calcolare.

Quando il calcolatore è a posto col cervello esso sa dare il significato corretto ad ogni numero che sta al suo interno.

Ma chi dice qual’è il significato corretto dei numeri?

Dare un significato ai numeri è il lavoro del programmatore.

Cos’è un programma.

Un programma è un insieme di numeri con un significato particolare. Sono le istruzioni che indicano al calcolatore cosa cambiare tra i suoi numeri. I programmi sono l’intelligenza del calcolatore.

Un programma può essere corretto oppure rotto.

Quando è corretto il calcolatore fa quello che il programmatore si aspetta, quando è rotto, il programma fa una cosa diversa dal previsto e il programmatore deve andare a cercare il problema e magari risolverlo.

Allora comandiamolo!

I primi programmatori facevano proprio così: bucavano dei foglietti di cartone per comunicare al calcolatore le istruzioni. Poi sono arrivati i nastri magnetici, i video le tastiere, i dischi e tanta memoria per il nostro calcolatore.

Infine abbiamo trovato una maniera più semplice per fare i programmi: invece di dirgli cosa fare gli descriviamo le cose come stanno e le regole tra le cose e lasciamo ad altri programmi il compito di tradurre la nostra descrizione in istruzioni.

Come si descrive la realtà.

Per descrivere la realtà bisogna avere una grande passione per la matematica, uno spirito di osservazione acuto, una pazienza smisurata e come in tutti i lavori il gusto del bello.

La passione per la matematica serve a formare nel nostro cervello una scatola degli attrezzi ben fornita, dove conosciamo i nostri attrezzi per nome, avendoli utilizzati a lungo. Questi strumenti si chiamano astrazioni.

Lo spirito di osservazione ci serve a capire quale astrazione si nasconde dietro la realtà che vogliamo descrivere.

La pazienza serve a mettere a posto gli errori che riempiono il lavoro del programmatore in ogni aspetto, da quando pensa a quando scrive il programma.

Il gusto per il bello serve a lottare per ottenere un risultato che oltre a funzionare ci fa sentire orgogliosi del nostro lavoro di scrittori di codice. Spesso stiamo svegli la notte per ripulire il nostro lavoro e per documentarlo, sebbene il risultato voluto l’abbiamo già ottenuto.

Tutte queste caratteristiche sono il frutto di una sfida con il nostro cervello, una sfida che ci piace.

Quanta fatica, ma dov’è il bello ?>

Il bello dell’informatica è che ci permette di capire le cose come funzionano, ci stimola ad analizzarle in maniera accurata, ci da fiducia nelle nostre capacità, ci fa sentire piccoli quando non capiamo i problemi e grandi quando li risolviamo e soprattutto ci insegna a essere logici, a non credere alle superstizioni e a svelare i trucchi del mondo che ci circonda.

Il calcolatore nel 2011

I calcolatori nel 2011 sono estremamente potenti. In uno smartphone ritroviamo la potenza di calcolo di un supercomputer degli anni 80. Questo ci porta a pensare che le applicazioni che popolano i nostri calcolatori siano sempre più esigenti. Questo è falso in generale.

Divagando leggermente possiamo esaminare la potenza di trasmissione dati della rete, che volendo trasportare contenuti sostanziosi in breve tempo sta seguendo la sua curva di crescita. Qui è evidente che il valore dei contenuti non aumenta con la banda della rete.

Un esempio clamoroso è *twitter* . Per questa applicazione che comprende la rete internet per funzionare, la potenza di calcolo necessaria a permetterci di leggere e scrivere i tweets e la banda necessaria a diffonderli è irrisoria. Infatti twitter è l’applicazione sociale preferita nei paesi dove potenza di calcolo e larghezza di banda sono ancora scadenti. Eppure questa applicazione ha permesso l’organizzazione di rivoluzioni di popolo.

Sempre di più, il calcolatore è valorizzato dalla qualità dei programmi che esegue e quindi dalla qualità media dei programmatori. In questo campo due tendenze di effetto contrario governano l’andamento della qualità. La prima, negativa, è l’appalto a cottimo della programmazione che sviluppa del codice usa e getta, e la seconda, positiva, è la diffusione della filosofia *open source*, che permette a tutti di cimentarsi nello sviluppo di codice di qualità tendenzialmente duraturo.

Informatica per ragazzi.

L’informatica nel nostro paese è insegnata tardi e male.

Come se non bastasse le wii e compagnia bella occupano già una fetta importante di rapporto tra i ragazzi e i calcolatori.

Giocare con la play può sviluppare alcune potenzialità cerebrali, ma la programmazione dei calcolatori è una passione e un divertimento ben diverso.

Saper programmare un calcolatore è fondamentale per la vita dell’uomo moderno. Purtroppo il percorso scolastico della scuola primaria ci propone di diventare utenti di un sistema operativo o peggio di una suite di programmi.

Sicuramente la capacità di programmare un foglio elettronico sarebbe già un ottimo risultato per la scuola primaria, ma credo che l’insegnamento della programmazione di base sia propedeutico a tutti i futuri passi come utenti consapevoli dei calcolatori.

Così come nello scrivere un programma si può utilizzare con successo una scrittura *top-down* (dalla visione generale al particolare) , così nell’insegnamento ai ragazzi che posseggono una cultura matematica di base si può utilizzare un linguaggio di programmazione di alto livello, per nascondere il più possibile gli elementi tecnici e concentrarsi nello sviluppo della logica del codice.

I ragazzi preparati al codice di alto livello avranno sviluppato delle buone basi per affrontare in seguito le sfide tecniche dei livelli inferiori.

Il corso è basato sul lavoro di Chris Smith consultabile sul suo blog