2012-04-17 3 views
8

Prendere nota della seconda riga in questa sessione GHCi. Di cosa si tratta del tipo Latitude che mi consente di usare un numero "nudo" come valore, invece di dover invocare un costruttore? Mi piacerebbe fare qualcosa di simile con alcuni dei miei tipi.Assegnazione di numeri "nudi" a nuovi tipi

λ> :m + Data.Geo.GPX.Type.Latitude                         
λ> let t = 45 :: Latitude                            
λ> t                                 
45.0 

Ho esaminato il codice sorgente per il tipo di latitudine, ma ho avuto difficoltà a capire che fuori in un primo momento. Alla fine ho trovato la risposta, quindi ho pensato di documentarlo qui. Vedi la mia risposta qui sotto.

risposta

4

In base allo standard Haskell98, i valori letterali numerici sono in realtà le chiamate a fromInteger e fromRational. Ciò consente loro di essere convertiti in qualsiasi tipo che implementa tali funzioni (fromInteger è nella classe Prelude.Num e fromRational è nella classe di esempi Prelude.Fractional).

La sintassi dei valori letterali numerici è riportata nella Sezione 2.5. Un numero intero letterale rappresenta l'applicazione della funzione da Intero al valore appropriato di di Numero intero. Analogamente, un valore letterale floating rappresenta un'applicazione diRational a un valore di tipo Rational (ovvero, Ratio Integer). Date le tipizzazioni:

fromInteger :: (Num a) => numero intero -> un

fromRational :: (frazionarie a) => Rational -> un intero

e letterali galleggianti hanno le tipizzazioni (Num a) => ae (Frazionario a) => a, rispettivamente. I valori letterali numerici sono definiti in in modo indiretto in modo che possano essere interpretati come valori di qualsiasi tipo numerico appropriato di . Vedere la Sezione 4.3.4 per una discussione sull'ambiguità di sovraccarico di .

http://www.haskell.org/onlinereport/basic.html#numeric-literals

6

Ciò che rende questo lavoro è che il tipo è un Num. Il modo più semplice per farlo è usare "derivando Num", nel qual caso ho bisogno del pragma di linguaggio GeneralizedNewtypeDeriving. Così posso creare un tipo come la seguente,

newtype Seconds = Seconds Double deriving (Eq, Ord, Enum, Num, Fractional, Floating, Real, RealFrac, RealFloat, Show) 

E poi nel GHCi,

λ> let s = 5 :: Seconds                            
λ> s                                 
Seconds 5.0 

In alternativa, ho potuto implementare in modo esplicito Num.

+4

Per essere precisi, è il fatto che 'seconds' è nella classe' Num' che lo fa funzionare. Non importa come sia diventato un membro della classe 'Num'. – augustss

+2

Funzionerebbe anche se l'istanza fosse fornita esplicitamente anziché derivata. Tutto ciò di cui hai bisogno è un 'Num di istanza '. –

+0

Grazie augusts e Daniel. Ho aggiornato la risposta. – mhwombat