91 votes

Pourquoi ce code Haskell de produire le "infini" type d'erreur?

Je suis nouveau sur Haskell et face à un "ne peut pas construire infini" type d'erreur que je ne peut pas donner un sens.

En fait, au-delà, je n'ai pas été en mesure de trouver une bonne explication de ce qu'est cette erreur signifie même, donc si vous pouviez aller au-delà de ma question de base et expliquer le "infini" type d'erreur, je l'apprécierais vraiment.

Voici le 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

Et voici l'erreur en essayant de le charger dans l'interpréteur:

Prélude> :charge ./chapitre.3.fin.réel.monde.haskell.des exercices.hs [1 1] Compilation Principal ( chapitre.3.fin.réel.monde.haskell.des exercices.hs, interprété )

chapitre.3.fin.réel.monde.haskell.des exercices.hs:147:0: Se vérifier: ne peut pas construire l'infini type: a = [a] Lors de la généralisation du type(s) pour `imposer' A échoué, les modules chargés: aucun.

Merci.

EDIT: Merci pour les réponses, j'ai corrigé le code et j'ai aussi une ligne directrice générale pour les relations avec les "infini" type d'erreur en Haskell:

Code corrigé

intersperse _ [] = []
intersperse _ [x] = x
intersperse s (x:xs) =  x ++ s:intersperse s xs

Quel était le problème:

Mon type de signature états que le deuxième paramètre de ponctuer est une liste de listes. Donc, quand j'modèle mis en correspondance avec "s (x:y:xs)", x et y sont devenus des listes. Et pourtant j'ai été le traitement de x et y comme des éléments, et non pas des listes.

La ligne directrice pour les relations avec les "infini" type d'erreur:

La plupart du temps, lorsque vous obtenez cette erreur, vous avez oublié les types des différentes variables que vous avez affaire, et vous avez tenté d'utiliser une variable comme si elle était d'un autre type que ce qu'il est. Regardez attentivement à ce type de tout ce qui est rapport à la façon dont vous l'utilisez, et il s'agit généralement de découvrir le problème.

38voto

Stephan202 Points 27707

Le problème est dans le dernier alinéa, où vous traiter de x et y comme des éléments, alors qu'ils sont des listes. Cela va fonctionner:

intersperse _ [] = []
intersperse _ [x] = x 
intersperse s (x:y:xs) = x ++ [s] ++ y ++ intersperse s xs

L'infini type d'erreur se produit car l' : opérateur de type a -> [a] -> [a], tandis que vous le traiter comme [a] -> a -> [a], ce qui signifie que [a] doit être identifié avec un, ce qui voudrait dire que l'un est infiniment liste imbriquée. Qui n'est pas autorisé (et pas ce que tu veux dire, de toute façon).

Edit: il y a aussi un autre bug dans le code ci-dessus. Il devrait être:

intersperse _ [] = []
intersperse _ [x] = x
intersperse s (x:xs) = x ++ [s] ++ intersperse s xs

8voto

Joey Points 161

Souvent l'ajout d'un type explicite de définition peut faire le compilateur du type de message d'erreur plus de sens. Mais dans ce cas, l'explicite tapant permet au compilateur de message d'erreur pour le pire.

Regardez ce qui se passe lorsque je laisse ghc deviner le type de ponctuer:

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'

Qui dirige clairement vers le bug dans le code. En utilisant cette technique, vous n'avez pas à regarder tout et de réfléchir sur les types, comme d'autres, ont suggéré de le faire.

3voto

Samir Talwar Points 9307

J'ai peut-être tort, mais il semble que vous essayez de résoudre un problème plus difficile à résoudre. Votre version de intersperse ne vient ponctuer la valeur du tableau, mais aussi aplatit un niveau.

L' List module en Haskell fournit en fait une parsemer de fonction. Il met en valeur donnée entre chaque élément de la liste. Par exemple:

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"]

Je suppose que c'est ce que vous voulez faire, car c'est ce que mon professeur voulait nous faire quand j'étais en train d'apprendre Haskell. Je pourrais, bien sûr, être totalement.

1voto

Dacav Points 2536

J'ai aussi trouvé ce qui explique la signification de l'erreur.

Chaque fois que l'interpréteur/compilateur me donne cette erreur c'est parce que je suis en utilisant un certain type-paramétrées, un tuple comme paramètre formel. Tout fonctionne correctement par suppression de la définition de type de la fonction, ce qui était contenant les variables de type.

Je n'arrive toujours pas à comprendre comment à la fois le fixer et de maintenir la fonction de la définition de type.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X