2009-04-27 2 views
59

Я новичок в Haskell и сталкиваюсь с ошибкой «не могу построить бесконечный тип», о которой я не могу понять.Почему этот код Haskell создает ошибку «бесконечного типа»?

Фактически, кроме того, я не смог найти хорошее объяснение того, что означает эта ошибка, поэтому, если бы вы могли выйти за рамки моего основного вопроса и объяснить ошибку «бесконечного типа», я бы очень признателен Это.

Вот код:

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 

А вот ошибка при попытке загрузить его в интерпретатор:

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. 

Спасибо.

-

Вот некоторые исправленный код и общее руководство по работе с ошибкой "бесконечный типа" в Haskell:

исправленного код

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

Какого проблема была:

Мой тип подпись состояние s, что вторым параметром для интерполяции является список списков. Поэтому, когда я сопоставлялся с «s (x: y: xs)», x и y становились списками. И все же я рассматривал x и y как элементы, а не списки.

Руководства по работе с ошибкой «бесконечный типа»:

Большой частью времени, когда вы получите эту ошибку, вы забыли типы различных переменные, которые вы имеете дело с, и вы попытались использовать переменную, как если бы это был какой-то другой тип, чем тот, который есть. Посмотрите внимательно, что у вас есть, и как вы его используете, и это, как правило, выявляет проблему.

+1

Еще один хороший совет: явным образом объявляю типы. Это дает компилятору что-то, что нужно проверить. –

+1

Итак, это решает проблему, но почему компилятор говорит: «Невозможно построить бесконечный тип?». Что это значит? Если проблема заключается в том, что вы пытаетесь выполнять операции над типами, которые не поддерживают эти операции, почему компилятор не говорит что-то подобное? – freedrull

+9

+1 для структуры вопроса (вопрос исправлен - проблема была - ориентир) – Dacav

ответ

27

Проблема заключается в последнем пункте, где вы рассматриваете x и y как элементы, в то время как они являются списками. Это будет работать:

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

ошибка бесконечного типа происходит потому, что: оператор имеет тип а -> [а] -> [а], в то время как вы относиться к нему как [а] -> а -> [а] , что означает, что [a] должно быть идентифицировано с a, что означает, что a - бесконечно вложенный список. Это не допустимо (а не то, что вы имеете в виду, так или иначе).

Редактировать: есть еще одна ошибка в приведенном выше коде. Это должно быть:

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

Спасибо. Я понял, что вы оба, а затем вернулся сюда и увидел ваш ответ, который был отличным подтверждением для меня. Вы также исправили мою ошибку лучше, чем я. Моя ошибка заключалась в том, что она пропускала разделитель между y и xs. Чтобы исправить это, я ввел еще один уровень соответствия шаблонов, например: intersperse s (x: y: []) = x ++ s: y intersperse s (x: y: xs) = intersperse s [x, y] ++ s: intersperse s xs Но похоже, что вы исправили ошибку, не требуя этого дополнительного уровня. –

+1

Вот урок, который я узнал: «Когда вы сталкиваетесь с ошибкой« бесконечного типа », вы, вероятно, забываете, с какими типами вы имеете дело, и поэтому делаете то, что вы не хотели делать. Осторожно посмотрите, какой тип каждого из ваших переменные есть, и это, как правило, раскрывает проблему ». Есть ли что-нибудь, что вы могли бы добавить или изменить? –

+0

Это, конечно, правильно, и я ничего не изменил бы в этом.Бесконечные типы не допускаются, и, следовательно, ошибка бесконечного типа означает, что где-то функции получают аргумент с неправильным типом. Удачи с RWH :) – Stephan202

2

Возможно, я ошибаюсь, но, похоже, вы пытаетесь решить более сложную проблему. Ваша версия intersperse не просто пересекает значение с массивом, но также выравнивает его на один уровень.

Модуль List в Haskell фактически обеспечивает функцию пересечения. Он вводит значение, заданное между , каждый элемент в списке.Например:

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

Я предполагаю, что это то, что вы хотите сделать, потому что это то, что мой профессор хотел, чтобы мы делали, когда я учился Haskell. Я мог бы, конечно, полностью разобраться.

+0

Спасибо за комментарий. В этом случае, однако, я хочу сгладить его на один уровень, потому что я делаю упражнение 7 с конца главы 3 «Real World Haskell». –

+0

Gotcha. Если бы у меня была книга, я бы проверил, прежде чем писать. Увы, все, что я мог сделать, это догадываться. Рад, что вы все разобрались. :-) –

+4

Содержание книги свободно доступно в Интернете: http://book.realworldhaskell.org/ – Stephan202

0

Также я нашел this, который объясняет значение ошибки.

Каждый раз, когда интерпретатор/компилятор дает мне эту ошибку, это потому, что я использую некоторый тип-параметризованный кортеж как формальный параметр. Все работает правильно , удаляя тип определения функции, которая содержит переменные типа.

Я до сих пор не могу понять, как исправить это и сохранить определение типа функции.

3

Часто добавляя явное определение типа, можно сделать сообщение об ошибке типа компилятора более разумным. Но в этом случае явное типирование делает сообщение об ошибке компилятора хуже.

Посмотрите, что происходит, когда я позволил GHC угадать тип пересыпать:

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' 

Это явно указывает в сторону ошибки в коде. Используя эту технику, вам не нужно смотреть на все и думать о типах, как это предлагали другие.

Смежные вопросы