Ciao! Se è la prima volta che capiti su questo sito, ti consiglio di consultare la pagina principale di questo cosiddetto Giardino Digitale per scoprire meglio cosâè e come navigarlo.
Lo stato di questa nota è al momento: đ´ Bozza.
Come già detto, Haskell ha un sistema di tipi statico. Ciò significa che il tipo di ogni espressione è noto a tempo di compilazione, il che ci porta ad avere un codice piÚ sicuro. Se scrivi un programma in cui provi a dividere un booleano con qualche numero, non ti permette neanche di compilare. Ciò ci va piÚ che bene perchÊ è meglio catturare questo tipo di errori a tempo di compilazione anzichÊ far crashare il progrmma. Ogni cosa in Haskell ha un tipo.
Definizione: tipo in Haskell
In Haskell, un tipo è unâetichetta che descrive quali valori può assumere unâespressione. Haskell ha una tipizzazione statica, cioè il tipo dellâespressione viene determinato a tempo di compilazione, ed è fortemente tipizzato, cioè non permette a una espressione di cambiare tipo durante lâesecuzione del programma.
:t (abbreviazione di :type) è un comando di GHCi che mostra la firma di tipo di unâespressione senza valutarla.
Now weâll use GHCi to examine the types of some expressions. Weâll do that by using the :t command which, followed by any valid expression, tells us its type. Letâs give it a whirl.
Here we see that doing :t on an expression prints out the expression followed by :: and its type. :: is read as âhas type ofâ. Explicit types are always denoted with the first letter in capital case. 'a', as it would seem, has a type of Char. Itâs not hard to conclude that it stands for character. True is of a Bool type. That makes sense. But whatâs this? Examining the type of "HELLO!" yields a [Char]. The square brackets denote a list. So we read that as it being a list of characters. Unlike lists, each tuple length has its own type. So the expression of (True, 'a') has a type of (Bool, Char), whereas an expression such as ('a','b','c') would have the type of (Char, Char, Char). 4 == 5 will always return False, so its type is Bool.
Functions also have types. When writing our own functions, we can choose to give them an explicit type declaration. This is generally considered to be good practice except when writing very short functions. From here on, weâll give all the functions that we make type declarations. Remember the list comprehension we made previously that filters a string so that only caps remain? Hereâs how it looks like with a type declaration.
removeNonUppercase :: [Char] -> [Char] removeNonUppercase st = [c | c <- st, c `elem` ['A'..'Z']]
removeNonUppercase has a type of [Char] -> [Char], meaning that it maps from a string to a string. Thatâs because it takes one string as a parameter and returns another as a result. The [Char] type is synonymous with String so itâs clearer if we write removeNonUppercase :: String -> String. We didnât have to give this function a type declaration because the compiler can infer by itself that itâs a function from a string to a string but we did anyway. But how do we write out the type of a function that takes several parameters? Hereâs a simple function that takes three integers and adds them together:
addThree :: Int -> Int -> Int -> IntaddThree x y z = x + y + z
The parameters are separated with -> and thereâs no special distinction between the parameters and the return type. The return type is the last item in the declaration and the parameters are the first three. Later on weâll see why theyâre all just separated with -> instead of having some more explicit distinction between the return types and the parameters like Int, Int, Int -> Int or something.
If you want to give your function a type declaration but are unsure as to what it should be, you can always just write the function without it and then check it with :t. Functions are expressions too, so :t works on them without a problem.
Hereâs an overview of some common types.
Definizione: tipo Int
Int è un tipo in Haskell usato per rappresentare i numeri interi (in inglese integer numbers). Ă un tipo bounded e sulle macchine a 32 bit lâintervallo di valori corrisponde a [â2147483648,2147483647].
Definizione: tipo Integer
Integer è un tipo in Haskell usato per rappresentare i numeri interi (in inglese integer numbers) ma, a differenza del tipo Int, non è bounded e, quindi, può essere usato per rappresentare numeri molto piÚ grandi o piÚ piccoli.
Definizione: tipo Float
Float è un tipo in Haskell usato per rappresentare i numeri reali a virgola mobile (in inglese real floating point) con precisione singola.
Definizione: tipo Double
Double è un tipo in Haskell usato per rappresentare i numeri reali a virgola mobile (in inglese real floating point) con precisione doppia (da qui il nome del tipo).
Definizione: tipo Bool
Bool è un tipo in Haskell usato per rappresentare i valori booleani di verità . Può assumere solo i valori True e False.
Definizione: tipo Char
Char è un tipo in Haskell usato per rappresentare i caratteri, delimitati da singole virgolette ''.
Variabili di tipi
Secondo te qual è il tipo della funzione head? Non è una domanda banale, perchÊ head prende una lista di un tipo qualsiasi ne restituisce il primo elemento, quindi quale tipo assume? Controlliamo su GHCi:
ghci> :t head head :: [a] -> a
Hmmm! What is this a? Is it a type? Remember that we previously stated that types are written in capital case, so it canât exactly be a type. Because itâs not in capital case itâs actually a type variable. That means that a can be of any type. This is much like generics in other languages, only in Haskell itâs much more powerful because it allows us to easily write very general functions if they donât use any specific behavior of the types in them. Functions that have type variables are called polymorphic functions. The type declaration of head states that it takes a list of any type and returns one element of that type.
Definizione: variabile di tipo
In Haskell una variabile di tipo è un segnaposto generico nel tipo di una funzione o struttura datie generalmente si indica con una singola lettera minuscola (a, b, c, âŚ).
Remember fst? It returns the first component of a pair. Letâs examine its type.
ghci> :t fst fst :: (a, b) -> a
We see that fst takes a tuple which contains two types and returns an element which is of the same type as the pairâs first component. Thatâs why we can use fst on a pair that contains any two types. Note that just because a and b are different type variables, they donât have to be different types. It just states that the first componentâs type and the return valueâs type are the same.
Classi di tipi
Definizione: classe di tipo
In Haskell una classe di tipo è un insieme di tipi che condividono un insieme di operazioni.
Qual è il tipo della funzione ==? Controlliamo su GHCi:
ghci> :t (==) (==) :: (Eq a) => a -> a -> Bool
Interesting. We see a new thing here, the => symbol. Everything before the => symbol is called a class constraint. We can read the previous type declaration like this: the equality function takes any two values that are of the same type and returns a Bool. The type of those two values must be a member of the Eq class (this was the class constraint).
Eq è una classe di tipo su cui è definita lâuguaglianza strutturale e appartiene a essa qualsiasi tipo i cui valori possono essere confrontati tra loro con le funzioni == e /=.
Definizione: classe di tipo Ord
Ord è una classe di tipo a cui appartiene qualsiasi tipo i cui valori possono essere ordinati tra loro, per esempio usando gli operatori >, <, >= e <=.
Definizione: tipo Ordering
Ordering è un tipo in Haskell usato per rappresentare il confronto tra due valori. Può assumere solo i seguenti tre valori:
LT: sta per less than (in italiano minore di) e indica che il primo valore è minore del secondo.
EQ: sta per equal to (in italiano uguale a) e indica che i due valori sono uguali.
GT: sta per greater than (in italiano maggiore di) e indica che il primo valore è maggiore del secondo.
La funzione compare prende due valori dello stesso tipo appartenente alla classe di tipo Ord e restituisce un Ordering che descrive la relazione dâordine tra i due:
Show è una classe di tipo a cui appartiene qualsiasi tipo i cui valori possono essere convertiti in una stringa, per esempio tramite la funzione show.
Definizione: classe di tipo Read
Read è una classe di tipo a cui appartiene qualsiasi tipo i cui valori possono essere ottenuti dal parsing di una stringa, per esempio tramite la funzione read. Ă in un certo senso lâinverso di Show.
Definizione: funzione show
La funzione show prende un valore di qualsiasi tipo appartenente alla classe di tipo Show e restituisce la sua rappresentazione come stringa:
ghci> show 42"42"ghci> show 3.14"3.14"ghci> show True"True"
Definizione: funzione read
La funzione read prende una stringa e la converte in un valore di qualsiasi tipo appartenente alla classe di tipo Read. Ă lâinverso di show e richiede spesso unâannotazione di tipo esplicita per disambiguare il tipo restituito:
Enum è una classe di tipo a cui appartiene qualsiasi tipo i cui valori sono enumerabili, ovvero hanno un predecessore e un successore ben definiti. Questo permette di usarli nelle range notation delle liste, come [LT .. GT] o ['a' .. 'z'].
Definizione: classe di tipo Bounded
Bounded è una classe di tipo a cui appartiene qualsiasi tipo che ha un valore minimo e un valore massimo, accessibili tramite le funzioni minBound e maxBound.
Definizione: classe di tipo Num
Num è una classe di tipo a cui appartiene qualsiasi tipo numerico i cui valori supportano le operazioni aritmetiche di base, come +, - e *.
Definizione: classe di tipo Integral
Integral è una classe di tipo a cui appartiene qualsiasi tipo numerico intero, come Int e Integer. Estende Num e aggiunge la divisione intera e il modulo tramite le funzioni div e mod.
Definizione: classe di tipo Floating
Floating è una classe di tipo a cui appartiene qualsiasi tipo numerico in virgola mobile, come Float e Double. Estende Num e aggiunge operazioni matematiche avanzate come sqrt, sin, cos e **.
Fonti
đ Miran LipovaÄa, Learn You a Haskell for Great Good!: