Как упражнение, я пытаюсь определить значение ruler
ruler :: (Num a, Enum a) => [a]
который соответствует функции линейки
0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2...
где n
'-й элемент списка (при условии, что первый элемент соответствует n=1
), является наибольшей степенью 2, которая равномерно делит n
. Чтобы сделать его более интересным, я пытаюсь реализовать ruler
, не выполняя никаких тестов на делимость.
Используя вспомогательную функцию
interleave :: [a] -> [a] -> [a]
который просто чередует элементы из двух приведенных списков, я придумал это, но, увы, он не работает:
interleave :: [a] -> [a] -> [a]
interleave (x:xs) (y:ys) = x : y : interleave xs ys
interleave _ _ = []
ruler :: (Num a, Enum a) => [a]
ruler = foldr1 interleave . map repeat $ [0..]
main :: IO ()
main = print (take 20 ruler)
В конечном итоге программа использует все пространство стека.
Теперь, что странно, что программа работает нормально, если я настраиваю определение interleave
так, чтобы он читал
interleave (x:xs) ys = x : head ys : interleave xs (tail ys)
т.е. Я больше не использую сопоставление шаблонов во втором аргументе. Почему использование head
и tail
здесь делает ruler
terminate - в конце концов, сопоставление шаблонов является довольно защитным (я только оцениваю первый элемент списка позвонков, нет?).