2013-05-29 17 views
19

Ho una domanda su come GHCi assume il tipo di un numero intero.Haskell: SìNo digitare classe. Perché integer?

Stavo leggendo Sì-No tipo classe di Learn you a Haskell.

Questo è un collegamento se si desidera leggere il tutto. http://learnyouahaskell.com/making-our-own-types-and-typeclasses#a-yes-no-typeclass

Per dirla in breve, questo capitolo mostra che definendo la mia classe, posso creare una funzione che funzioni con molti tipi.

Questo libro definisce classe YesNo con una funzione

yesno :: a -> Bool 

e fare Int come un'istanza della classe YesNo

instance YesNo Int where 
    yesno 0 = False 
    yesno _ = True 

Quando ho caricato questo sul mio GHCi e digitato

yesno 0 

ha restituito l'errore. Ho pensato che probabilmente è perché GHCi non è in grado di stabilire se 0 è inteso come Int o Integer o Double o altro tipo nella classe Num. In realtà quando ho digitato yesno (0 :: Int) ha funzionato.

Quindi, solo per divertimento ho fatto Integer come esempio di YesNo di classe e ha scritto

instance YesNo Integer where 
    yesno 0 = True 
    yesno _ = False 

(Si noti che ho capovolto Vero e Falso) e ancora una volta, ho digitato

yesno 0 

(senza qualsiasi tipo di dichiarazione) quindi GHCi ha mostrato True.

Inoltre, quando ho digitato

yesno $ fromIntegral 0 

è tornato True, il che significa che GHCi pensa che il tipo di fromIntegral 0 è Integer.

Quindi, questo significa che quando digito un numero intero su GHCi, di solito si assume che il suo valore sia Integer invece di? Sono confuso, perché :t 0 rendimenti Num a => a

risposta

24

È il tipo defaulting insieme alle regole predefinite estese di ghci.

I valori letterali interi sono polimorfici, hanno il tipo Num a => a (poiché rappresentano fromInteger literal). Ma quando deve essere valutata un'espressione - necessaria per stampare il suo risultato, per esempio - l'espressione deve essere data un tipo monomorfico.

Di per sé,

yesno 0 

impone i due vincoli Num a e YesNo a sulla 0, e l'intera espressione avrebbe il tipo ambiguo

yesno 0 :: (Num a, YesNo a) => Bool 

(è ambigua, poiché la variabile del tipo a il vincolo non è raggiungibile dal tipo a destra di =>).

In genere, i tipi ambigui sono errori di tipo, tuttavia, in alcuni casi l'ambiguità viene risolta creando un'istanza della variabile di tipo vincolata con un tipo predefinito. Le regole della specifica del linguaggio sono che una variabile di tipo può essere in default se

In situazioni in cui viene scoperto un tipo ambiguo, un tipo di variabile ambigua, v, è defaultable se:

- `v` appears only in constraints of the form `C v`, where `C` is a class, and 
- at least one of these classes is a numeric class, (that is, `Num` or a subclass of `Num`), and 
- all of these classes are defined in the Prelude or a standard library (Figures 6.2–6.3 show the numeric classes, and Figure 6.1 shows the classes defined in the Prelude.) 

Il vincolo (Num a, YesNo a) soddisfa i primi due requisiti, ma non il terzo. Quindi, secondo lo standard del linguaggio, non è defaultabile e dovrebbe essere un errore di tipo.

Tuttavia, ghci utilizza le regole predefinite estese e anche le variabili di tipo predefinite vincolate da classi non definite nel Preludio o nelle librerie standard.

Sarebbe quindi scegliere il valore predefinito per un vincolo Num qui, a meno che una dichiarazione di default esplicita è di portata, che sarebbe Integer, o, se Integer non soddisfa i vincoli, Double è provato.

Quindi, quando si dispone di un instance YesNo Integer, ghci può predefinito con successo il tipo di variabile a-Integer. Ma senza questa istanza disponibile, l'impostazione predefinita non riesce perché nessuno dei candidati predefiniti ha un'istanza.

8

Quindi, questo significa che quando mi basta digitare un numero intero su GHCi, di solito assume il suo valore è intero?

Sì. Fondamentalmente, GHCi proverà per prima cosa Integer, quindi se fallisce, Double e infine () per risolvere i vincoli di tipo ambigui. È possibile read the details about how this works in the GHC User's Guide.

Tuttavia, si noti che nei moduli compilati le regole sono un po 'più rigide. In particolare, l'impostazione predefinita si applica solo alle classi standard, quindi l'esempio non funzionerà senza un'annotazione di tipo in un modulo compilato a meno che non si abiliti l'estensione ExtendedDefaultRules che offre lo stesso comportamento di GHCi.

1

nel primo caso provare a scrivere:

Prelude> yesno (0 :: Int) 
False 
Problemi correlati