Каноническая реализация length :: [a] -> Int
является:Как написать функцию длины постоянного пространства в Haskell?
length [] = 0
length (x:xs) = 1 + length xs
, который очень красиво, но страдает от переполнения стека, как он использует линейное пространство.
Хвостовой рекурсией версия:
length xs = length' xs 0
where length' [] n = n
length' (x:xs) n = length xs (n + 1)
не страдает от этой проблемы, но я не понимаю, как это может работать в постоянном пространстве ленивым языке.
Разве это не время, накопившее множество (n + 1)
thunks, когда оно перемещается по списку? Должна ли эта функция Haskell потреблять пространство O (n) и привести к переполнению стека?
(если это имеет значение, я использую GHC)
Код опроса действительно переполняет стек. Вообще говоря, в Haskell хвостовая рекурсия делает ** не ** делать то, что вы ожидаете от нее, а ленивые хвостовые рекурсивные функции часто являются ошибками. См. Здесь: http://www.haskell.org/haskellwiki/Foldr_Foldl_Foldl. Правило большого пальца: либо сделайте его строгим, как 'foldl'', либо заставьте его возвратить в конструктор, например' foldr'. –
Aw, орехи. По-видимому, Markdown не любит апострофы в конце URL-адреса. Попробуем еще раз: http://www.haskell.org/haskellwiki/Foldr_Foldl_Foldl%27 –