pierotofy (Admin)
Guru^2
Messaggi: 6230
Iscritto: 04/12/2003
|
Qualcuno potrebbe darmi una breve spiegazione dell'utilità del tipo (o modificatore?) Maybe?
Codice sorgente - presumibilmente Plain Text |
> :t Just "ciao"
Just "ciao" :: Maybe [Char]
|
In quale contesto pratico viene usato?
Edit: ok, capisco che Maybe definisce un tipo "nullable" (un tipo che può ritornare Nothing). Ma Just?
Ultima modifica effettuata da pierotofy il 26/01/2015 alle 23:26
|
|
lumo (Member)
Expert
Messaggi: 449
Iscritto: 18/04/2010
|
Il tipo Maybe è definito circa così come probabilmente sai:
Codice sorgente - presumibilmente Haskell |
data Maybe a = Just a | Nothing deriving (blabla )
|
Quelli a destra dell'uguale sono i costruttori per il tipo Maybe. E' comune che a volte i costruttori non abbiano lo stesso nome del tipo che "creano", in questo caso ha senso.
Di fatto un costruttore per Maybe a altro non è che una funzione con tipo (parametri...) -> Maybe a.
Il compilatore da quelle due indicazioni per il costruttore crea due funzioni cone questo tipo:
Codice sorgente - presumibilmente Haskell |
A prima vista il tipo Maybe potrebbe sembrare in tutto e per tutto un tipo nullable, come dici tu. (A questo proposito, anche se off topic: http://www.infoq.com/presentations/Null-References-The-Bil ..., lol)
In Haskell però non si fa quasi mai un check esplicito su un dato di tipo Maybe a per vedere se sia Nothing o qualcosa, altrimenti il codice diventerebbe presto ingestibile.
Un esempio semplice: supponi di avere
Codice sorgente - presumibilmente Haskell |
Purtroppo i numeri provengono da un parser che gestisce l'opportunità di errore attraverso Maybe:
Codice sorgente - presumibilmente Haskell |
Se volessimo sommare i due numeri dovremmo fare
Codice sorgente - presumibilmente VB.NET |
let n1 = parseNumber input1 n2 = parseNumber input2 in case n1 of Just x -> case n2 of Just y -> Just (somma x y) Nothing -> Nothing Nothing -> Nothing
|
Tutta questa espressione ha come tipo Maybe Int (questo è quello che si intende quando si dice che il typesystem di haskell mantiene la distinzione tra codice puro e codice con side effects: non è più possibile estrarre il tipo "Int" da "Maybe Int").
Tuttavia siccome è alquanto brutto, conviene definire una funzione che faccia un po' di pulizia:
Codice sorgente - presumibilmente VB.NET |
applyMaybeBinary :: (Maybe a -> Maybe b -> Maybe c) -> Maybe a -> Maybe b applyMaybeBinary fun Nothing _ = Nothing applyMaybeBinary fun _ Nothing = Nothing applyMaybeBinary fun (Just x) (Just y) = fun x y
|
Ora potremmo riscrivere l'espressione di prima come:
Codice sorgente - presumibilmente Haskell |
let n1 = parseNumber input1 n2 = parseNumber input2 in applyMaybeBinary somma n1 n2
|
La funzione applyMaybeBinary ci permette di usare qualsiasi generica funzione binaria con parametri di tipo Maybe. Funzioni higher order di questo tipo sono molto comuni in haskell e questa operazione è solitamente detta di lifting, perché fai lavorare la funzione su tipi "superiori".
Fortunatamente tutto ciò è integrato nella libreria standard di haskell:
http://hackage.haskell.org/package/base-4.7.0.2/docs/Data- ...
http://hackage.haskell.org/package/base-4.7.0.2/docs/Contr ...
Un programmatore haskell riscriverebbe il codice sopra così:
Codice sorgente - presumibilmente Haskell |
import Control.Applicative ... let n1 = parseNumber input1 n2 = parseNumber input2 in (liftA2 (+)) n1 n2
|
Oppure più idiomaticamente
Codice sorgente - presumibilmente Plain Text |
Ultima modifica effettuata da lumo il 29/01/2015 alle 1:26 |
|
pierotofy (Admin)
Guru^2
Messaggi: 6230
Iscritto: 04/12/2003
|
Grazie per la spiegazione!
Più precisamente, ero un pò confuso dal fatto che non si potesse fare qualcosa del genere:
Codice sorgente - presumibilmente Haskell |
data Maybe a = a | Nothing
|
La grammatica del linguaggio richiede che ci sia un 'data constructor' (Just). Leggerò alcune volte quello che hai scritto per assicurarmi di aver capito.
|
|
lumo (Member)
Expert
Messaggi: 449
Iscritto: 18/04/2010
|
Postato originariamente da pierotofy:
Grazie per la spiegazione!
Più precisamente, ero un pò confuso dal fatto che non si potesse fare qualcosa del genere:
Codice sorgente - presumibilmente Haskell |
data Maybe a = a | Nothing
|
La grammatica del linguaggio richiede che ci sia un 'data constructor' (Just). Leggerò alcune volte quello che hai scritto per assicurarmi di aver capito.
|
Il motivo per cui quello non è possibile è più filosofico(e poi si riflette nella sintassi): in Haskell non esiste il subtyping.
null in un linguaggio OOP normalmente può essere il valore di qualsiasi variabile, perché se Object è nullable allora tutte le sue sottoclassi lo sono.
In haskell di solito invece di progettare con l'ereditarietà e il subtyping si usa il data polymorphism, le informazioni implicite che vengono date dalla gerarchia si trasferiscono esplicitamente nel polimorfismo dei tipi.
Da quello che so Scala combina questi due approci, ma a quanto dice Simon Peyton-Jones (il creatore di Haskell) questo rende il type system molto complesso. |
|
ZioCrocifisso (Member)
Pro
Messaggi: 135
Iscritto: 06/03/2013
|
Postato originariamente da pierotofy:
Grazie per la spiegazione!
Più precisamente, ero un pò confuso dal fatto che non si potesse fare qualcosa del genere:
Codice sorgente - presumibilmente Haskell |
data Maybe a = a | Nothing
|
La grammatica del linguaggio richiede che ci sia un 'data constructor' (Just). Leggerò alcune volte quello che hai scritto per assicurarmi di aver capito.
|
I "data" sono tagged union, e il costruttore rappresenta il tag. Dev'esserci sempre, altrimenti non si saprebbe a quale costruttore ci si sta riferendo. I Maybe possono essere usati come nullable, ma Nothing non è assolutamente un null, è un valore come tutti gli altri. Negli altri linguaggi è possibile fare una distinzione tra il valore esistente e il null perché il null è un valore che i riferimenti a un dato esistente non possono mai assumere. La confusione che quella struttura genererebbe si può notare se si crea un valore di tipo Maybe (Maybe Int). Se il valore fosse "Nothing", si tratterebbe del costruttore del primo Maybe o di quello più interno? Con il data corretto, il Nothing del Maybe esterno sarebbe "Nothing", quello interno "Just Nothing". Nel tuo caso non sarebbe possibile distinguerli. In Haskell esistono effettivamente i puntatori e quelli nulli, ma vengono usati soltanto per interagire con librerie scritte in altri linguaggi, per esempio C, perché sono insicuri e portano a bug. |
|