Я изучаю Haskell и использую следующее выражение на Haskell Wiki действительно озадачил меня:
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
Я не могу понять, почему это работает.
Если я применяю стандартную логику каррирования (zipWith (+))
возвращает функцию, которая принимает список в качестве аргумента, а в Turn возвращает другую функцию, которая принимает в качестве аргумента другой список, и возвращает список ( zipWith: :( a -> b -> c) -> [a] -> [b] -> [c]
). Итак, fibs
- это ссылка на список (который еще не был оценен), а (хвостовые аргументы)
- это конец того же (неоцененного) списка. Когда мы пытаемся вычислить ( взять 10 fibs
), первые два элемента привязаны к 0
и 1
. Другими словами fibs == [0,1,?,? ...]
и (хвостик) == [1,?,?,?]
. После завершения первого сложения fibs
становится [0,1,0 + 1,?, ..]
. Точно так же после второго сложения мы получаем [0,1,0 + 1,1 + (0 + 1),?,? ..]
выдумал !! 4
? РЕДАКТИРОВАТЬ2: Я только что нашел заданный выше вопрос и хорошо ответил здесь . Прошу прощения, если я потратил чье-то время.
РЕДАКТИРОВАТЬ: вот более сложный для понимания случай (источник: Форумы проекта Euler ):
filterAbort :: (a -> Bool) -> [a] -> [a]
filterAbort p (x:xs) = if p x then x : filterAbort p xs else []
main :: Int
main = primelist !! 10000
where primelist = 2 : 3 : 5 : [ x | x <- [7..], odd x, all (\y -> x `mod` y /= 0) (filterAbort (<= (ceiling (sqrt (fromIntegral x)))) primelist) ]
Обратите внимание, что все (\ y -> x mod y / = 0) ...
Как ссылка на x здесь НЕ может вызывать бесконечную рекурсию?