2014-04-02 15 views
12

Ho trovato questo codice nel pacchetto unm-hip. Quindi Pixel è una funzione?Cosa significa la stella in questo codice haskell?

class Imageable i where 
    type Pixel i :: * 
    rows :: i -> Int 
    cols :: i -> Int 
    ref :: i -> Int -> Int -> (Pixel i) 
    makeImage :: Int -> Int -> PixelOp (Pixel i) -> i 
    pixelList :: i -> [Pixel i] 
    pixelList i = [ ref i r c | r <- [0..(rows i - 1)], c <- [0..(cols i - 1)]] 

risposta

15

Come estensione di Haskell standard, è possibile gestire "tipi". I tipi sono un tipo di sistema di base molto semplice per i costruttori di tipi e tipi. Il tipo * è un tipo semplice, ad esempio Int. Il tipo * -> * è un costruttore di tipi che accetta un tipo e produce un tipo, ad esempio Maybe: passa un tipo come Int come argomento e ottieni il tipo Maybe Int.

L'altra estensione utilizzata in questo codice (che non ho notato all'inizio, poiché il rientro è stato perso) è associata ai tipi. Un typeclass in Haskell standard può specificare un numero di funzioni che il tipo deve supportare. Con i tipi associati, può inoltre specificare tipi e costruttori di tipi associati al tipo.

Qui, questo significa che un tipo i che è un'istanza di Imageable (cioè comporta come un'immagine) deve avere un tipo di pixel associato Pixel i, e questo deve essere un tipo semplice (tipo *), non è un tipo di costruzione.

+0

Sai perché l'autore del codice usa questo disegno? – osager

+2

Non c'è molta scelta. Hai un tipo di tipo che rappresenta un'immagine, e la classe di caratteri richiede delle funzioni che si occupano di un singolo pixel nell'immagine. Hai bisogno di un modo per scoprire quale sia il tipo di quel pixel. Puoi sistemarlo, ma non è molto flessibile. Potresti rendere Imageable un typeclass multi-param sull'immagine e il suo pixel, ma poi hai bisogno di dipendenze funzionali o di tipo ambiguities ti farà impazzire, e devi ancora menzionare il tipo di pixel in ogni firma che usa la classe. I tipi associati sono molto più puliti e più facili. –

1

"Quindi Pixel è una funzione?"

Pixel è una funzione di livello del tipo. Richiede un singolo tipo (che deve essere un'istanza di Imageable) e restituisce un tipo di tipo '*'. Sulla base del suo utilizzo nel codice di esempio, il tipo di input deve essere di tipo "*". Quindi, Pixel è molto simile a Maybe, sono entrambi "type constructors" di tipo "* -> *", tu fornisci loro un "tipo semplice" e restituiscono un "tipo semplice". Sono validi anche nelle stesse posizioni. Proprio come non è possibile avere una funzione di tipo "Foo -> Maybe", non sarà possibile avere una funzione di tipo "Bar -> Pixel".

+0

Quindi la parola chiave 'type' non è come con una parola chiave di tipo haskell Type right? Se è come hai detto, perché non è scritto in questo modo: 'digita Pixel :: i -> *' – osager

+1

@osager È correlato, ma non è lo stesso. Quando fornisci un'istanza (Imagable my_image), la definizione per Pixel deve essere di tipo esistente e (Pixel my_image) sarà un alias/sinonimo per quel tipo. È un'estensione GHC chiamata famiglie di tipi (aperti). –