#haskell
Вопрос:
Если я использую tail в следующей функции (которая предназначена для обмена числами в списке 2 на 2), она компилируется и работает нормально:
pairExchange :: [a] -> [a]
pairExchange [] = []
pairExchange [a] = [a]
pairExchange (x:xs) | length xs > 2 = head xs : x : pairExchange (tail xs)
| otherwise = head xs : x : tail xs
но если я использую «последний xs» в последней строке вместо «хвост xs» (что было бы то же самое, так как список будет содержать только 2 элемента), я получу следующую ошибку:
«Происходит проверка: не удается построить бесконечный тип: a ~ [a]»
Я хотел бы знать, почему это так, заранее благодарю вас.
Комментарии:
1.
tail :: [a] -> [a]; last :: [a] -> a
. То естьlast
возвращает элемент, а не список. Но ты привел верный аргумент, чтобы(:) :: a -> [a] -> [a]
. Затем вывод типа пытается рассматривать список как список списков и завязывается в узлы.2. Кое — что, над чем вам может понравиться ломать голову: как вы думаете, что пойдет не так, если вы полностью откажетесь от проверки длины (и
otherwise
предложения)? Согласен ли GHC с вами? (Эта головоломка не имеет отношения к вашей проблеме.)
Ответ №1:
У них разные типы:
λ> :t last
last :: [a] -> a
λ> :t tail
tail :: [a] -> [a]
Следовательно last xs
, имеет тип a и tail xs
имеет тип [a].
В этом случае Occurs check: cannot construct the infinite type: a ~ [a]
означает, что он нашел a, когда ожидал [a].
Демонстрация:
λ> :t (:)
(:) :: a -> [a] -> [a]
λ> :{
f :: [a] -> [a]
f xs = head xs : last xs -- (1)
:}
<interactive>:102:35: error:
• Occurs check: cannot construct the infinite type: a ~ [a]
λ> :{
f :: [a] -> [a]
f xs = head xs : [last xs] -- (2)
:}
λ> f [1,2,3]
[1,3]
В (1) last xs
имеет тип a. В (2) [last xs]
имеет тип [a].