Почему этот код 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
в чем проблема была:
подпись моего типа утверждает, что второй параметр для intersperse-это список списков. Поэтому, когда я сопоставил шаблон с "s (x:y:xs)", x и y стали списки. И все же я рассматривал x и y как элементы, а не списки.
руководство по работе с ошибкой "бесконечного типа":
большую часть времени, когда вы получаете эту ошибку, вы забыли типы различных переменных, с которыми вы имеете дело, и вы попытались использовать переменную, как если бы это был какой-то другой тип, чем то, что он есть. Посмотрите внимательно на то, какой тип все это по сравнению с тем, как вы его используете, и это обычно будет раскрыть проблему.
4 ответа:
проблема заключается в последнем предложении, где вы рассматриваете x и y как элементы, в то время как они являются списками. Это будет работать:
intersperse _ [] = [] intersperse _ [x] = x intersperse s (x:y:xs) = x ++ [s] ++ y ++ intersperse s xs
ошибка бесконечного типа возникает потому, что оператор : имеет тип a -> [a] -> [a], в то время как вы рассматриваете его как [a] -> a -> [A], что означает, что [a] должен быть идентифицирован с a, что означало бы, что a является бесконечно вложенным списком. Это не допускается (и не то, что вы имеете в виду, во всяком случае).
Edit: есть также еще одна ошибка в приведенном выше код. Это должно быть:
intersperse _ [] = [] intersperse _ [x] = x intersperse s (x:xs) = x ++ [s] ++ intersperse s xs
часто добавление явного определения типа может сделать сообщение об ошибке типа компилятора более разумным. Но в этом случае явная типизация делает сообщение об ошибке компилятора хуже.
посмотрите, что происходит, когда я позволяю ghc угадать тип intersperse:
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'
, что явно указывает на ошибку в коде. Используя эту технику, вам не нужно смотреть на все и думать о типах, как предлагали другие.
Я могу ошибаться, но, похоже, вы пытаетесь решить более сложную проблему. Ваша версия
intersperse
не просто перемежает значение с массивом, но и выравнивает его на один уровень.The
List
модуль в Haskell фактически обеспечивает функцию intersperse. Он помещает значение, заданное между элемент в списке. Например: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"]
Я предполагаю, что это то, что вы хотите сделать, потому что это то, что мой профессор хотел, чтобы мы сделали, когда Я учился у Хаскелла. Конечно, я мог бы полностью отключиться.
также я нашел этой что объясняет смысл ошибки.
каждый раз, когда интерпретатор/компилятор дает мне эту ошибку, это потому, что я использую какой-то тип-параметризованный Кортеж в качестве формального параметра. Все правильно удаление определение типа функции, которая содержала переменные типа.
Я все еще не могу понять, как исправить это и сохранить определение типа функции.