fibs :: [Int]
fibs = 0 : 1 : [ a + b | (a, b) <- zip fibs (tail fibs)]
Это генерирует последовательность Fibonacci.
Я понимаю поведение защиты, :
, zip
и tail
, но я не понимаю <-
. Что это делает здесь?
Из-за большого количества голосов я превратил свой комментарий в ответ.
То, что вы видите, не является защитой, но это понимание списка. Для начала подумайте, что это способ выразить математическую нотацию множества, например A = { x | x элемент N }, что означает примерно следующее: Множество A - это множество всех натуральных чисел. При понимании списка это будет [x | x <- [1...] ]
.
Вы также можете использовать ограничения на числа: [x | x <- [1...], x `mod` 2 == 0 ]
и многое другое.
Существует множество хороших учебников по haskell, посвященных пониманию списков, и даже вопрос на StackOverflow о ресурсах haskell.
Единственная сложность - это молнии (хвосты)
. zip
просто составляет попарный список из каждого из своих аргументов. Итак, если у вас есть два таких списка:
[ 1, 2, 3, 4 ]
[ "a", "b", "c", "d" ]
Их заархивирование приведет к:
[ (1,"a"), (2,"b"), (3,"c"), (4,"d") ]
Стрелка влево (назначение в шаблон деструктуризации) просто извлекает парные элементы, чтобы их можно было сложить вместе. Два архивируемых списка - это fibs
и (tail fibs)
- другими словами, последовательность Фибоначчи и последовательность Фибоначчи, смещенная на 1 элемент. Haskell оценивается лениво, поэтому он может вычислить список для любого необходимого количества элементов. Это относится и к zip.
Понимание списка в скобках:
[ a + b | (a, b) <- zip fibs (tail fibs)]
возвращает список, содержащий результат (a + b), где переменные a и b получены в результате
zip fibs (tail fibs)
Давайте расширим его.
zip
создает пары из содержимого двух списков. Итак, первая пара застежек-молний (хвостов)
дает нам (0, 1)
, что в сумме дает 1. Итак, теперь список [0,1, 1]
. Теперь мы знаем три элемента в списке, поэтому понимание списка может продолжаться, захватывая следующий элемент из списка и следующий элемент из хвоста, что дает (1,1)
- сложенные вместе, что дает 2 Затем мы получаем следующую пару, которая равна (1,2)
, что составляет следующее число в последовательности 3. Это может продолжаться бесконечно, так как понимание всегда будет обеспечивать достаточное количество элементов.
Для чего это стоит, мне легче понять следующую версию:
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)