2012-02-28 17 views
5

i seguenti controlli tipo di programma se a specificare sulla riga di comando (ad es ghci file.hs):ghci - raccolta desiderosa in modalità interattiva?

import Data.Ratio 
foo = let x = [1..] 
      y = (1%2) + (head x) 
     in y 

Tuttavia, se entro in modo interattivo Prendo un errore di tipo:

Prelude> import Data.Ratio 
Prelude Data.Ratio> let x = [1..] 
Prelude Data.Ratio> let y = (1%2) + (head x) 
<interactive>:1:23: 
    Couldn't match expected type `Ratio a0' with actual type `Integer' 

E ' sembra che x venga digitato impazientemente come [Integer] rispetto al più generale (Num t, Enum t) => [t].

C'è qualcosa che posso fare al riguardo? Ci sono altre situazioni in cui la modalità interattiva sarà diversa dalla modalità batch?

+1

restrizione monomorfismo ... – augustss

+1

e digita moroso – Ptival

+3

Infatti, è la restrizione monomorfismo temuta. Ci sono due modi per aggirarlo: dare una firma esplicita o disattivare questa restrizione (in GHCi, si può fare ': set -XNoMonomorphismRestriction' e il gioco è fatto, anche le istruzioni del linguaggio e i flag del compilatore funzionano. – Vitus

risposta

10

Associazioni senza argomenti, vale a dire quelli della forma x = ... sono soggetti a il monomorphism restriction, il che significa che GHC proverà a renderlo non polimorfico usando qualsiasi tipo di informazione disponibile e ricadendo su type defaulting per risolvere qualsiasi amb iguities. (In realtà, GHCi utilizza a slightly more permissive set of defaulting rules, ma questo non ha molta importanza per questa domanda).

Dato che non sono disponibili altre informazioni di tipo quando si scrive let x = [1..], il tipo predefinito causa il tipo da dedurre come [Integer], poiché Integer è il tipo numerico predefinito.

Ci sono diversi modi per risolvere questo problema:

  1. uso della firma tipo. Funziona sempre, ma a volte può essere noioso quando si lavora con tipi complessi.

    > let x = [1..] :: [Rational] 
    
  2. Scrivi il legame con gli argomenti. Questo non si applica nel tuo caso, ma a volte si vede questo problema quando si scrivono definizioni di funzioni point-free.

    > let f = (+) 
    > :t f 
    f :: Integer -> Integer -> Integer 
    > let f x y = x + y 
    > :t f 
    f :: Num a => a -> a -> a 
    
  3. Dare il tipo di controllo ulteriori informazioni. Nel tuo caso potremmo evitare il problema scrivendo entrambe le associazioni in una dichiarazione let. GHC può quindi utilizzare le informazioni sul tipo della seconda associazione per dedurre correttamente che x dovrebbe avere il tipo [Rational].

    > let x = [1..]; y = 1%2 + head x 
    > :t x 
    x :: [Ratio Integer] 
    
  4. disattivare la restrizione monomorfismo. Questo può avere gravi implicazioni sulle prestazioni se ti aspettavi che il tipo di qualcosa fosse, ad es. un Num a => a, dal momento che quest'ultimo deve essere ricalcolato ogni volta mentre il primo può essere condiviso. Questo è il motivo principale per cui la restrizione esiste in primo luogo.

    Tuttavia, nell'interprete questo è in genere meno un problema, quindi la convenienza è spesso la pena.

    > :set -XNoMonomorphismRestriction 
    > let x = [1..] 
    > :t x 
    x :: (Num t, Enum t) => [t] 
    

    Se si desidera che questo per impostazione predefinita, è possibile aggiungere al vostro .ghci file.

4

È può fare qualcosa al riguardo, definendo x essere la seguente:

let x = [1..] :: [Ratio Int] 

come in:

Data.Ratio Prelude> let x = [1..] :: [Ratio Int] 
Data.Ratio Prelude> let y = (1%2) + (head x) 
Data.Ratio Prelude> y 
3 % 2 
Data.Ratio Prelude> 
+1

Sconsiglio vivamente di usare 'Ratio Int', a meno che tu non sappia assolutamente che il tuo calcolo non può traboccare e sei disperato per le prestazioni - e anche allora non mi piace. Secondo me è stato un brutto errore fare di "Ratio" un tipo polimorfico, anche calcoli di piccole dimensioni possono facilmente superare i 64 bit, e quindi si ottengono assurdità. –

Problemi correlati