2010-12-14 10 views
2

Ich mag gerne wissen, warum Haskell dieseFehler in Haskell "kann nicht unendlich Typ erstellen"

perms xs = [ x:y | i <- [0..(length xs - 1)], x <- [xs!!i], y <- perms (takeOut i xs)] 

akzeptiert aber nicht akzeptieren, dass:

perms xs = [ x:(perms y) | i <- [0..(length xs - 1)], x <- [xs!!i], y <- (takeOut i xs)] 

Sie wirft

[1 von 1] Kompilierhaupt (abc.hs, interpretiert)

Occurs check: cannot construct the infinite type: t = [t] 
    Expected type: t -> [t] 
    Inferred type: [t] -> [[a]] 
In the second argument of `(:)', namely `(perms y)' 
In the expression: x : (perms y) 

Ich kann verstehen, was es sagt, ich kann einfach nicht ist, warum der erste ist in Ordnung und der zweite ist nicht!

EDIT: Ah, natürlich habe ich auch

perms [] = [[]] 

an der Spitze.

Dank

+2

'(x, i) <- zip xs [0 ..]' anstelle von 'i <- [0 .. (Länge xs - 1)], x <- [xs !! i] 'ist viel besser –

+0

Ja ist es! Vielen Dank! –

Antwort

3

In einer Liste Verständnis, bindet x <- ysx-jedes Element in ys. Im Wesentlichen sind Sie versuchen zu verwandeln:

[ f foo | foo <- bar ] 

In

[ f bar ] 

Die Phrase

y <- perms (takeOut i xs) 

Mittel "für jede Permutation y von takeOut i xs". So die [ x:y | ... ] vor x zu jeder Permutation.

Entsprechend ist der Begriff

y <- takeOut i xs 

Means "für jedes Element y von takeOut i xs". So versucht die [ x:perms y | ... ] alle Permutationen der Elementy (nicht einmal eine Liste) zu finden, und dann x zu dieser Liste von Permutationen vor. Die Permutationen von etwas ist eine Liste von Listen, so x muss eine Liste sein, um dies zu tun, was es nicht ist. Also, im Grunde macht der zweite keinen Sinn.

Ich kann sehen, warum Sie würde abgeworfen werden. Denken Sie daran, ist nicht dasselbe wie let, es bedeutet für jeden.

8

Im ersten Ausdruck haben Sie x:y was bedeutet, dass, wenn x :: a dann y :: [a]. In x : perms y wenn x :: a dann muss es perms y :: [a] sein, aber perms y :: [[a]] (Liste der Permutationen). Typchecker versucht, [a] und [[a]] zu vereinheitlichen und schlägt fehl.

+0

Diese Antwort ist übermäßig technisch und gibt keine Intuition für die Quelle des Fehlers. – luqui

4

Mein Gehirn tut weh und ich bin kein Experte, aber ich denke:

In

perms xs = [ x:y | i <- [0..(length xs - 1)], x <- [xs!!i], y <- perms (takeOut i xs)] 

perms (Takeout i xs) ist eine Liste von Listen. x ist auf jedes Element dieser Liste konzentriert. Perms wird in der Liste als Ganzes aufgerufen, also ist perms eine Funktion, die eine Liste von Dingen aufnimmt.

In

perms xs = [ x:(perms y) | i <- [0..(length xs - 1)], x <- [xs!!i], y <- (takeOut i xs)] 

(TAKEOUT i xs) ist eine Liste, und für jedes Element dieser Liste wird auf x perms dieses Element Consed. Perms wird für jedes Element der Liste aufgerufen, so dass perms eine Funktion übernimmt.

Nur der ehemalige Fall ist intern konsistent, und der Typchecker liebt dich.