Ich bin neu in Haskell und habe den Fehler "Ich kann keinen unendlichen Typ konstruieren", den ich nicht verstehen kann.
Darüber hinaus konnte ich keine gute Erklärung dafür finden, was dieser Fehler überhaupt bedeutet. Wenn Sie also über meine grundlegende Frage hinausgehen und den Fehler "Unendlicher Typ" erklären könnten, würde ich ihn wirklich begrüßen.
Hier ist der Code:
intersperse :: a -> [[a]] -> [a]
-- intersperse '*' ["foo","bar","baz","quux"]
-- should produce the following:
-- "foo*bar*baz*quux"
-- intersperse -99 [ [1,2,3],[4,5,6],[7,8,9]]
-- should produce the following:
-- [1,2,3,-99,4,5,6,-99,7,8,9]
intersperse _ [] = []
intersperse _ [x] = x
intersperse s (x:y:xs) = x:s:y:intersperse s xs
Und hier ist der Fehler beim Versuch, ihn in den Interpreter zu laden:
Prelude> :load ./chapter.3.ending.real.world.haskell.exercises.hs
[1 of 1] Compiling Main (chapter.3.ending.real.world.haskell.exercises.hs, interpreted )
chapter.3.ending.real.world.haskell.exercises.hs:147:0:
Occurs check: cannot construct the infinite type: a = [a]
When generalising the type(s) for `intersperse'
Failed, modules loaded: none.
Vielen Dank.
- -
Hier einige korrigierte den Code und eine allgemeine Richtlinie für den Umgang mit dem Fehler "Unendlicher Typ" in Haskell:
Code korrigiert
intersperse _ [] = []
intersperse _ [x] = x
intersperse s (x:xs) = x ++ s:intersperse s xs
Was war das Problem:
Meine Typensignatur besagt, dass der zweite Parameter, der eingestreut werden soll, eine Liste von Listen ist . Wenn ich ein Muster mit "s (x: y: xs)" übereinstimmte, wurden x und y daher zu Listen . Und doch behandelte ich x und y als Elemente, nicht als Listen.
Richtlinie für den Umgang mit dem Fehler "Unendlicher Typ":
Wenn Sie diesen Fehler erhalten, haben Sie meistens die Typen der verschiedenen Variablen vergessen, mit denen Sie sich befassen, und Sie haben versucht, eine Variable so zu verwenden, als wäre sie ein anderer Typ als der, der sie ist. Schauen Sie sich genau an, um welchen Typ es sich handelt und wie Sie ihn verwenden. Dadurch wird das Problem normalerweise aufgedeckt.
quelle
a
, von denen jeder für sich in Ordnung wäre. Es kann also nicht auf einen von ihnen zeigen und sagen "das ist eine nicht unterstützte Operation für diesen Typ". Aber zusammen fügen sie befriedigend für einen Typ einer Anforderung bisa = [a]
. Der Compiler weiß, dass dies unmöglich ist, und sagt Ihnen dies. Es ist nicht bekannt, welche Teile des Codes, die zu dieser Anforderung geführt haben, die falschen Teile sind. Das hängt davon ab , was Sie beabsichtigt , den Code zu verstehen.Antworten:
Das Problem liegt in der letzten Klausel, in der Sie x und y als Elemente behandeln, während es sich um Listen handelt. Das wird funktionieren:
intersperse _ [] = [] intersperse _ [x] = x intersperse s (x:y:xs) = x ++ [s] ++ y ++ intersperse s xs
Der unendliche Typfehler tritt auf, weil der Operator: den Typ a -> [a] -> [a] hat, während Sie ihn als [a] -> a -> [a] behandeln, was bedeutet, dass [a] mit identifiziert werden muss a, was bedeuten würde, dass a eine unendlich verschachtelte Liste ist. Das ist nicht erlaubt (und sowieso nicht das, was du meinst).
Bearbeiten: Es gibt auch einen anderen Fehler im obigen Code. Es sollte sein:
intersperse _ [] = [] intersperse _ [x] = x intersperse s (x:xs) = x ++ [s] ++ intersperse s xs
quelle
where you treat x and y as elements, while they are lists.
Warum sind sie Listen, das hast du nicht erklärt? Inx:xs
,x
ist ein Element, nicht wahr? Ich hatte gehofft, dass esx:y:xs
auch so sein wird. Wenn es sich um Listen handelt, wie werden sie aufgeteilt und enthalten wie viele Elemente? Ich denke eins?Oft kann das Hinzufügen einer expliziten Typdefinition die Typfehlermeldung des Compilers sinnvoller machen. In diesem Fall verschlimmert die explizite Eingabe die Fehlermeldung des Compilers.
Schauen Sie, was passiert, wenn ich ghc die Art der Streuung erraten lasse:
Occurs check: cannot construct the infinite type: a = [a] Expected type: [a] -> [[a]] -> [[a]] Inferred type: [a] -> [[a]] -> [a] In the second argument of `(:)', namely `intersperse s xs' In the second argument of `(:)', namely `y : intersperse s xs'
Das deutet eindeutig auf den Fehler im Code hin. Mit dieser Technik müssen Sie nicht auf alles starren und über die Typen nachdenken, wie andere vorgeschlagen haben.
quelle
Ich kann mich irren, aber es scheint, dass Sie versuchen, ein schwierigeres Problem zu lösen. Ihre Version von verteilt
intersperse
den Wert nicht nur auf das Array, sondern glättet ihn auch um eine Ebene.Das
List
Modul in Haskell bietet tatsächlich eine Zwischenfunktion. Es gibt den Wert ein, der zwischen jedem Element in der Liste angegeben ist. Zum Beispiel:intersperse 11 [1, 3, 5, 7, 9] = [1, 11, 3, 11, 5, 11, 7, 11, 9] intersperse "*" ["foo","bar","baz","quux"] = ["foo", "*", "bar", "*", "baz", "*", "quux"]
Ich gehe davon aus, dass Sie dies tun möchten, weil mein Professor dies von uns wollte, als ich Haskell lernte. Ich könnte natürlich total raus sein.
quelle
Auch ich fand dies, was die Bedeutung des Fehlers erklärt.
Jedes Mal, wenn der Interpreter / Compiler diesen Fehler ausgibt, verwende ich ein typparametrisiertes Tupel als formalen Parameter. Alles funktioniert korrekt, indem die Typdefinition der Funktion entfernt wird, die Typvariablen enthielt.
Ich kann immer noch nicht herausfinden, wie ich das Problem beheben und die Definition des Funktionstyps beibehalten kann.
quelle