2013-09-04 9 views
7
data NestedList a = Elem a | List [NestedList a] 
flatten :: NestedList a -> [a] 
flatten (Elem element) = [element] 
flatten (List []) = [] 
flatten (List (first:rest)) = flatten first ++ flatten (List (rest)) 
main = print $ flatten $ List [] 

Ho scritto il codice sopra visto in haskell. Quando eseguo questo con qualsiasi altro parametro, ad esempioNessuna istanza per (Mostra a0) derivante da un uso di `stampa 'La variabile di tipo` a0' è ambigua

main = print $ flatten $ List [Elem 1, Elem 2] 
main = print $ flatten $ Elem 1 

[1, 2] 
[1] 

rispettivamente.

Non riesce quando lo eseguo con una lista vuota.

main = print $ flatten $ List [] 

Messaggio di errore

No instance for (Show a0) arising from a use of `print' 
The type variable `a0' is ambiguous 
Possible fix: add a type signature that fixes these type variable(s) 
Note: there are several potential instances: 
    instance Show Double -- Defined in `GHC.Float' 
    instance Show Float -- Defined in `GHC.Float' 
    instance (Integral a, Show a) => Show (GHC.Real.Ratio a) 
    -- Defined in `GHC.Real' 
    ...plus 23 others 
In the expression: print 
In the expression: print $ flatten $ List [] 
In an equation for `main': main = print $ flatten $ List [] 

Domande

  1. Perché fallire e come posso risolvere questo problema?
  2. Devo modificare la definizione NestedList per accettare un numero vuoto List? Se è così, come faccio a farlo. È abbastanza confuso.
+3

GHC non ha informazioni quale tipo da utilizzare. Quando hai 'Elem 1', nella lista, hai fornito un vincolo' Num a', e quindi GHC ha potuto impostare la variabile type su 'Integer'. Senza elementi, non può default la variabile di tipo 'a0'. Dagli una firma tipo, 'main = print $ flatten $ (List [] :: NestedList())', ad esempio, in modo che il compilatore sappia quale tipo usare. –

+0

Perché il downvote? – thefourtheye

risposta

7

Il problema è che il compilatore non può conoscere il tipo di flatten $ List []. Cercate di capire il tipo di te stesso, vedrai che è [a] per qualche a, mentre print richiede il suo argomento sia un'istanza di Show, e [a] è un'istanza di Show se a è un'istanza di Show. Anche se la tua lista è vuota, quindi non è necessario alcun vincolo su a per rappresentare [], non c'è modo per il compilatore di sapere.

Come tale, mettendo tipo di annotazione esplicito (per qualsiasi tipo per la quale esiste un'istanza di Show) dovrebbe funzionare:

main = print $ flatten $ List ([] :: [NestedList Int]) 

o

main = print $ flatten $ List ([] :: [NestedList()]) 

o

main = print fl 
    where 
    fl :: [()] 
    fl = flatten $ List [] 
+0

Cosa significano i parenti vuoti dopo 'NestedList' e in' [()] '? – thefourtheye

+1

@thefourtheye '()' è una tupla size-zero. È una specie dell'equivalente di Haskell di "void". – MathematicalOrchid

+0

E haskell sa come stampare una tupla vuota? – thefourtheye

15

Il tipo di elenco è polimorfico. Dato che non si fornisce un elemento, solo il costruttore della lista vuota [], non c'è modo di inferire che tipo di lista sia.

E ': [] :: [Int]

o [] :: [Maybe (Either String Double)]. Chi ha da dire?

Sei. Fornisci un'annotazione di tipo per risolvere il polimorfismo, quindi GHC può inviare l'istanza dello spettacolo corretta.

E.g.

main = print $ flatten $ List ([] :: [Int]) 
2

[] può essere un elenco di float, stringhe, booleani o qualsiasi tipo di al l.Pertanto, print non sa quale istanza di show utilizzare.

Fare come dice il messaggio di errore e dare un tipo esplicito, come in ([] :: [Int]).

8

Per aggiungere qui alle risposte, è possibile obiettare "ma che importa che tipo di cose contiene il mio elenco? Non ce n'è alcuno in esso!"

Beh, prima di tutto, è facile da costruire situazioni in cui non è chiaro se l'elenco è vuoto, e comunque digitare il controllo odia guardare valori, si vuole solo guardare tipi. Ciò semplifica le cose, perché significa che quando si tratta di gestire i valori, si può essere certi di conoscere già tutti i tipi.

secondo luogo di tutti, in realtà fa importa che tipo di lista è, anche se è vuota:

ghci> print ([] :: [Int]) 
[] 
ghci> print ([] :: [Char]) 
"" 
Problemi correlati