Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΊΠ½ΠΈΠ³ΠΈ ΠΎΠ½Π»Π°ΠΉΠ½ Π½Π° Bookidrom.ru! БСсплатныС ΠΊΠ½ΠΈΠ³ΠΈ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΊΠ»ΠΈΠΊΠ΅

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«Π˜Π·ΡƒΡ‡Π°ΠΉ Haskell Π²ΠΎ имя Π΄ΠΎΠ±Ρ€Π°!Β». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 20

Автор ΠœΠΈΡ€Π°Π½ Π›ΠΈΠΏΠΎΠ²Π°Ρ‡Π°

Π‘Π²Ρ‘Ρ€Ρ‚ΠΊΠΈ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Π½Ρ‹ для Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ любой Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, Π³Π΄Π΅ Π²Ρ‹ вычисляСтС Ρ‡Ρ‚ΠΎ-Π»ΠΈΠ±ΠΎ Π·Π° ΠΎΠ΄ΠΈΠ½ ΠΎΠ±Ρ…ΠΎΠ΄ списка[8]. Если Π²Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ ΠΎΠ±ΠΎΠΉΡ‚ΠΈ список для Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Ρ‡Ρ‚ΠΎ-Π»ΠΈΠ±ΠΎ Π²Ρ‹Ρ‡ΠΈΡΠ»ΠΈΡ‚ΡŒ, скорСС всСго, Π²Π°ΠΌ Π½ΡƒΠΆΠ½Π° свёртка. Π’ΠΎΡ‚ ΠΏΠΎΡ‡Π΅ΠΌΡƒ свёртки, наряду с функциями map ΠΈ filter, – ΠΎΠ΄Π½ΠΈ ΠΈΠ· Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ часто ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹Ρ… Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΠΌ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠΈ.

Π€ΡƒΠ½ΠΊΡ†ΠΈΠΈ foldl1 ΠΈ foldr1

Π€ΡƒΠ½ΠΊΡ†ΠΈΠΈ foldl1 ΠΈ foldr1 Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π½ΠΎ Ρ‚Π°ΠΊ ΠΆΠ΅, ΠΊΠ°ΠΊ ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ foldl ΠΈ foldr, Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π½Π΅Ρ‚ нСобходимости явно Π·Π°Π΄Π°Π²Π°Ρ‚ΡŒ стартовоС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅. Они ΠΏΡ€Π΅Π΄ΠΏΠΎΠ»Π°Π³Π°ΡŽΡ‚, Ρ‡Ρ‚ΠΎ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ (ΠΈΠ»ΠΈ послСдний) элСмСнт списка являСтся стартовым элСмСнтом, ΠΈ Π·Π°Ρ‚Π΅ΠΌ Π½Π°Ρ‡ΠΈΠ½Π°ΡŽΡ‚ свёртку со ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ элСмСнтом. ΠŸΡ€ΠΈΠ½ΠΈΠΌΠ°Ρ это Π²ΠΎ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ maximum ΠΌΠΎΠΆΠ½ΠΎ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

maximum' :: (Ord a) => [a] -> a

maximum' = foldl1 max

ΠœΡ‹ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Π»ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ maximum, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ foldl1. ВмСсто использования Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ значСния функция foldl1 ΠΏΡ€Π΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ Ρ‚Π°ΠΊΠΎΠ²Ρ‹ΠΌ являСтся ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ элСмСнт списка, послС Ρ‡Π΅Π³ΠΎ пСрСмСщаСтся ΠΊ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌΡƒ. ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ всё, Ρ‡Ρ‚ΠΎ Π΅ΠΉ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ, – это бинарная функция ΠΈ сворачиваСмый лист! ΠœΡ‹ Π½Π°Ρ‡ΠΈΠ½Π°Π΅ΠΌ с Β«Π³ΠΎΠ»ΠΎΠ²Ρ‹Β» списка ΠΈ сравниваСм ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ элСмСнт с аккумулятором. Если элСмСнт большС аккумулятора, ΠΌΡ‹ сохраняСм Π΅Π³ΠΎ Π² качСствС Π½ΠΎΠ²ΠΎΠ³ΠΎ значСния аккумулятора; Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС сохраняСм староС. ΠœΡ‹ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‘ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ max Π² качСствС ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π° foldl1, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ½Π° Ρ€ΠΎΠ²Π½ΠΎ это ΠΈ Π΄Π΅Π»Π°Π΅Ρ‚: Π±Π΅Ρ€Ρ‘Ρ‚ Π΄Π²Π° значСния ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ большСС. К ΠΌΠΎΠΌΠ΅Π½Ρ‚Ρƒ Π·Π°Π²Π΅Ρ€ΡˆΠ΅Π½ΠΈΡ свёртки останСтся самый большой элСмСнт.

По ΡΠΊΠΎΠ»ΡŒΠΊΡƒ эти Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Ρ‚Ρ€Π΅Π±ΡƒΡŽΡ‚, Ρ‡Ρ‚ΠΎΠ±Ρ‹ сворачиваСмыС списки ΠΈΠΌΠ΅Π»ΠΈ хотя Π±Ρ‹ ΠΎΠ΄ΠΈΠ½ элСмСнт, Ρ‚ΠΎ, Ссли Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ ΠΈΡ… с пустым списком, ΠΏΡ€ΠΎΠΈΠ·ΠΎΠΉΠ΄Ρ‘Ρ‚ ошибка Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ выполнСния.

Π‘ Π΄Ρ€ΡƒΠ³ΠΎΠΉ стороны, Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ foldl ΠΈ foldr Ρ…ΠΎΡ€ΠΎΡˆΠΎ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ с пустыми списками. ΠŸΠΎΠ΄ΡƒΠΌΠ°ΠΉΡ‚Π΅, ΠΈΠΌΠ΅Π΅Ρ‚ Π»ΠΈ смысл свёртка для пустых списков Π² вашСм контСкстС. Если функция Π½Π΅ ΠΈΠΌΠ΅Π΅Ρ‚ смысла для пустого списка, Ρ‚ΠΎ, Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ, Π²Ρ‹ Π·Π°Ρ…ΠΎΡ‚ΠΈΡ‚Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ foldl1 ΠΈΠ»ΠΈ foldr1 для Π΅Ρ‘ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ свёрток

Для Ρ‚ΠΎΠ³ΠΎ Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠΊΠ°Π·Π°Ρ‚ΡŒ, насколько ΠΌΠΎΡ‰Π½Ρ‹ свёртки, ΠΌΡ‹ собираСмся Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ с ΠΈΡ… ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ нСсколько стандартных Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅Ρ‡Π½Ρ‹Ρ… Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ. Π’ΠΎ-ΠΏΠ΅Ρ€Π²Ρ‹Ρ…, Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅ΠΌ свою Π²Π΅Ρ€ΡΠΈΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ reverse:

reverse' :: [a] -> [a]

reverse' = foldl (\acc x -> x : acc) []

Π—Π΄Π΅ΡΡŒ ΠΌΡ‹ ΠΎΠ±Ρ€Π°Ρ‰Π°Π΅ΠΌ список, ΠΏΠΎΠ»ΡŒΠ·ΡƒΡΡΡŒ пустым списком ΠΊΠ°ΠΊ Π½Π°Ρ‡Π°Π»ΡŒΠ½Ρ‹ΠΌ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ аккумулятора, ΠΈ, обходя Π·Π°Ρ‚Π΅ΠΌ исходный список слСва, добавляСм Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ элСмСнт Π² Π½Π°Ρ‡Π°Π»ΠΎ аккумулятора.

Ѐункция \acc x -> x : acc – ΠΏΠΎΡ‡Ρ‚ΠΈ Ρ‚ΠΎ ΠΆΠ΅, Ρ‡Ρ‚ΠΎ ΠΈ опСрация :, Π·Π° ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ΠΌ порядка слСдования ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ². ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ reverse' ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅ΠΏΠΈΡΠ°Ρ‚ΡŒ ΠΈ Ρ‚Π°ΠΊ:

reverse' :: [a] -> [a]

reverse' = foldl (flip (:)) []

Π’Π΅ΠΏΠ΅Ρ€ΡŒ Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ product:

product' :: (Num a) => [a] -> a

product' = foldl (*) 1

Π§Ρ‚ΠΎΠ±Ρ‹ Π²Ρ‹Ρ‡ΠΈΡΠ»ΠΈΡ‚ΡŒ ΠΏΡ€ΠΎΠΈΠ·Π²Π΅Π΄Π΅Π½ΠΈΠ΅ всСх элСмСнтов списка, слСдуСт Π½Π°Ρ‡Π°Ρ‚ΡŒ с аккумулятора Ρ€Π°Π²Π½ΠΎΠ³ΠΎ 1. Π—Π°Ρ‚Π΅ΠΌ ΠΌΡ‹ выполняСм свёртку Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ (*), которая ΠΏΠ΅Ρ€Π΅ΠΌΠ½ΠΎΠΆΠ°Π΅Ρ‚ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ элСмСнт списка Π½Π° аккумулятор.

Π’ΠΎΡ‚ рСализация Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ filter:

filter' :: (a -> Bool) -> [a] -> [a]

filter' p = foldr (\x acc -> if p x then x : acc else acc) []

Π—Π΄Π΅ΡΡŒ Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ аккумулятора являСтся пустым списком. ΠœΡ‹ сворачиваСм список справа Π½Π°Π»Π΅Π²ΠΎ ΠΈ провСряСм ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ элСмСнт, ΠΏΠΎΠ»ΡŒΠ·ΡƒΡΡΡŒ ΠΏΡ€Π΅Π΄ΠΈΠΊΠ°Ρ‚ΠΎΠΌ p. Если p x Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ истину, элСмСнт x помСщаСтся Π² Π½Π°Ρ‡Π°Π»ΠΎ аккумулятора. Π’ ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС аккумулятор остаётся Π±Π΅Π· измСнСния.

НапослСдок Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ last:

last' :: [a] -> a

last' = foldl1 (\ x -> x)

Для получСния послСднСго элСмСнта списка ΠΌΡ‹ примСняСм foldr1. НачинаСм с Β«Π³ΠΎΠ»ΠΎΠ²Ρ‹Β» списка, Π° Π·Π°Ρ‚Π΅ΠΌ примСняСм Π±ΠΈΠ½Π°Ρ€Π½ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ, которая ΠΈΠ³Π½ΠΎΡ€ΠΈΡ€ΡƒΠ΅Ρ‚ аккумулятор ΠΈ устанавливаСт Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠΉ элСмСнт списка ΠΊΠ°ΠΊ Π½ΠΎΠ²ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ аккумулятора. Как Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΌΡ‹ достигаСм ΠΊΠΎΠ½Ρ†Π° списка, аккумулятор β€” Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ послСдний элСмСнт – возвращаСтся Π² качСствС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° свёртки.

Иной взгляд Π½Π° свёртки

Π•ΡΡ‚ΡŒ Π΅Ρ‰Ρ‘ ΠΎΠ΄ΠΈΠ½ способ ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²ΠΈΡ‚ΡŒ Ρ€Π°Π±ΠΎΡ‚Ρƒ ΠΏΡ€Π°Π²ΠΎΠΉ ΠΈ Π»Π΅Π²ΠΎΠΉ свёртки. Π‘ΠΊΠ°ΠΆΠ΅ΠΌ, ΠΌΡ‹ выполняСм ΠΏΡ€Π°Π²ΡƒΡŽ свёртку с Π±ΠΈΠ½Π°Ρ€Π½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ f ΠΈ стартовым Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ z. Если ΠΌΡ‹ примСняСм ΠΏΡ€Π°Π²ΡƒΡŽ свёртку ΠΊ списку [3,4,5,6], Ρ‚ΠΎ Π½Π° самом Π΄Π΅Π»Π΅ вычисляСм Π²ΠΎΡ‚ Ρ‡Ρ‚ΠΎ:

f 3 (f 4 (f 5 (f 6 z)))

Ѐункция f вызываСтся с послСдним элСмСнтом Π² спискС ΠΈ аккумулятором; ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ²ΡˆΠ΅Π΅ΡΡ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ пСрСдаётся Π² качСствС аккумулятора ΠΏΡ€ΠΈ Π²Ρ‹Π·ΠΎΠ²Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ с ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΠΌ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ, ΠΈ Ρ‚. Π΄. Если ΠΌΡ‹ ΠΏΡ€ΠΈΠΌΠ΅ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ f Π·Π° ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ слоТСния ΠΈ Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ Π·Π° Π½ΡƒΠ»ΡŒ, наш ΠΏΡ€ΠΈΠΌΠ΅Ρ€ прСобразуСтся Ρ‚Π°ΠΊ:

3 + (4 + (5 + (6 + 0)))

Или, Ссли Π·Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ + ΠΊΠ°ΠΊ ΠΏΡ€Π΅Ρ„ΠΈΠΊΡΠ½ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ, получится:

(+) 3 ((+) 4 ((+) 5 ((+) 6 0)))

Аналогичным ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ лСвая свёртка с Π±ΠΈΠ½Π°Ρ€Π½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ g ΠΈ аккумулятором z являСтся эквивалСнтом выраТСния

g (g (g (g z 3) 4) 5) 6

Если Π·Π°ΠΌΠ΅Π½ΠΈΡ‚ΡŒ Π±ΠΈΠ½Π°Ρ€Π½ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ Π½Π° flip (:) ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ [] ΠΊΠ°ΠΊ аккумулятор (выполняСм ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠ΅ списка), подобная запись эквивалСнтна ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ:

flip (:) (flip (:) (flip (:) (flip (:) [] 3) 4) 5) 6

Если Π²Ρ‹Ρ‡ΠΈΡΠ»ΠΈΡ‚ΡŒ это Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅, ΠΌΡ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ [6,5,4,3].

Π‘Π²Ρ‘Ρ€Ρ‚ΠΊΠ° бСсконСчных списков

Взгляд Π½Π° свёртки ΠΊΠ°ΠΊ Π½Π° ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΠ΅ ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΊ элСмСнтам списка ΠΏΠΎΠΌΠΎΠ³Π°Π΅Ρ‚ ΠΏΠΎΠ½ΡΡ‚ΡŒ, ΠΏΠΎΡ‡Π΅ΠΌΡƒ правая свёртка ΠΈΠ½ΠΎΠ³Π΄Π° ΠΎΡ‚Π»ΠΈΡ‡Π½ΠΎ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ с бСсконСчными списками. Π”Π°Π²Π°ΠΉΡ‚Π΅ Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅ΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ and с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ foldr, Π° ΠΏΠΎΡ‚ΠΎΠΌ Π²Ρ‹ΠΏΠΈΡˆΠ΅ΠΌ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ ΠΏΡ€ΠΈΠΌΠ΅Π½Π΅Π½ΠΈΠΉ, ΠΊΠ°ΠΊ ΠΌΡ‹ это Π΄Π΅Π»Π°Π»ΠΈ Π² ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΡ… ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°Ρ…. Π’ΠΎΠ³Π΄Π° ΠΌΡ‹ ΡƒΠ²ΠΈΠ΄ΠΈΠΌ, ΠΊΠ°ΠΊ Π»Π΅Π½ΠΈΠ²ΠΎΡΡ‚ΡŒ языка Haskell позволяСт ΠΏΡ€Π°Π²ΠΎΠΉ свёрткС ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ бСсконСчныС списки.

Ѐункция and ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ список Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ Ρ‚ΠΈΠΏΠ° Bool ΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ False, Ссли хотя Π±Ρ‹ ΠΎΠ΄ΠΈΠ½ ΠΈΠ· элСмСнтов Ρ€Π°Π²Π΅Π½ False; Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС ΠΎΠ½Π° Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ True. ΠœΡ‹ Π±ΡƒΠ΄Π΅ΠΌ ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΡ‚ΡŒ список справа, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ True ΠΊΠ°ΠΊ Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅. Π’ качСствС Π±ΠΈΠ½Π°Ρ€Π½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π±ΡƒΠ΄Π΅ΠΌ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ &&, ΠΏΠΎΡ‚ΠΎΠΌΡƒ Ρ‡Ρ‚ΠΎ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ True Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² Ρ‚ΠΎΠΌ случаС, ΠΊΠΎΠ³Π΄Π° всС элСмСнты списка истинны. Ѐункция && Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ False, Ссли хотя Π±Ρ‹ ΠΎΠ΄ΠΈΠ½ ΠΈΠ· ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² Ρ€Π°Π²Π΅Π½ False, поэтому Ссли ΠΌΡ‹ встрСтим Π² спискС False, Ρ‚ΠΎ аккумулятор Π±ΡƒΠ΄Π΅Ρ‚ установлСн Π² Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ False ΠΈ ΠΎΠΊΠΎΠ½Ρ‡Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Ρ‚Π°ΠΊΠΆΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ False, Π΄Π°ΠΆΠ΅ Ссли срСди ΠΎΡΡ‚Π°Π²ΡˆΠΈΡ…ΡΡ элСмСнтов списка обнаруТатся истинныС значСния.

and' :: [Bool] -> Bool

and' xs = foldr (&&) True xs

Зная, ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ foldr, ΠΌΡ‹ Π²ΠΈΠ΄ΠΈΠΌ, Ρ‡Ρ‚ΠΎ Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ and' [True,False,True] Π±ΡƒΠ΄Π΅Ρ‚ Π²Ρ‹Ρ‡ΠΈΡΠ»ΡΡ‚ΡŒΡΡ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

True && (False && (True && True))

ПослСднСС True здСсь – это Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ аккумулятора, Ρ‚ΠΎΠ³Π΄Π° ΠΊΠ°ΠΊ ΠΏΠ΅Ρ€Π²Ρ‹Π΅ Ρ‚Ρ€ΠΈ логичСских значСния взяты ΠΈΠ· списка [True,False,True]. Если ΠΌΡ‹ ΠΏΠΎΠΏΡ€ΠΎΠ±ΡƒΠ΅ΠΌ Π²Ρ‹Ρ‡ΠΈΡΠ»ΠΈΡ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ этого выраТСния, получится False.

А Ρ‡Ρ‚ΠΎ Ссли ΠΏΠΎΠΏΡ€ΠΎΠ±ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚ΠΎ ΠΆΠ΅ самоС с бСсконСчным списком, скаТСм, repeat False? Если ΠΌΡ‹ Π²Ρ‹ΠΏΠΈΡˆΠ΅ΠΌ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠ΅ примСнСния, Ρ‚ΠΎ получится Π²ΠΎΡ‚ Ρ‡Ρ‚ΠΎ:

False && (False && (False && (False …

Π›Π΅Π½ΠΈΠ²ΠΎΡΡ‚ΡŒ Haskell ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΡ‚ Π²Ρ‹Ρ‡ΠΈΡΠ»ΠΈΡ‚ΡŒ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ Π΄Π΅ΠΉΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ. Ѐункция && устроСна Ρ‚Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Ссли Π΅Ρ‘ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ False, Ρ‚ΠΎ Π²Ρ‚ΠΎΡ€ΠΎΠΉ просто игнорируСтся, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΈ Ρ‚Π°ΠΊ ясно, Ρ‡Ρ‚ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ False.

Ѐункция foldr Π±ΡƒΠ΄Π΅Ρ‚ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ с бСсконСчными списками, Ссли бинарная функция, ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ ΠΌΡ‹ Π΅ΠΉ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‘ΠΌ, Π½Π΅ Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΠ³ΠΎ вычислСния Π²Ρ‚ΠΎΡ€ΠΎΠ³ΠΎ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π°, Ссли значСния ΠΏΠ΅Ρ€Π²ΠΎΠ³ΠΎ Π΅ΠΉ достаточно для вычислСния Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°. Π’Π°ΠΊΠΎΠ²Π° функция && – Π΅ΠΉ Π½Π΅Π²Π°ΠΆΠ½ΠΎ, ΠΊΠ°ΠΊΠΎΠ² Π²Ρ‚ΠΎΡ€ΠΎΠΉ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€, ΠΏΡ€ΠΈ условии, Ρ‡Ρ‚ΠΎ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ β€” False.

Π‘ΠΊΠ°Π½ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅

Π€ΡƒΠ½ΠΊΡ†ΠΈΠΈ scanl ΠΈ scanr ΠΏΠΎΡ…ΠΎΠΆΠΈ Π½Π° foldl ΠΈ foldr, Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠ½ΠΈ ΡΠΎΡ…Ρ€Π°Π½ΡΡŽΡ‚ всС ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½Ρ‹Π΅ значСния аккумулятора Π² список. Π’Π°ΠΊΠΆΠ΅ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΡƒΡŽΡ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ scanl1 ΠΈ scanr1, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΡΠ²Π»ΡΡŽΡ‚ΡΡ Π°Π½Π°Π»ΠΎΠ³Π°ΠΌΠΈ foldl1 ΠΈ foldr1.

ghci> scanl (+) 0 [3,5,2,1]

[0,3,8,10,11]

ghci> scanr (+) 0 [3,5,2,1]

[11,8,3,1,0]

ghci> scanl1 (\acc x –> if x > acc then x else acc) [3,4,5,3,7,9,2,1]

[3,4,5,5,7,9,9,9]

ghci> scanl (flip (:)) [] [3,2,1]

[[],[3],[2,3],[1,2,3]]

ΠŸΡ€ΠΈ использовании Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ scanl Ρ„ΠΈΠ½Π°Π»ΡŒΠ½Ρ‹ΠΉ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ окаТСтся Π² послСднСм элСмСнтС ΠΈΡ‚ΠΎΠ³ΠΎΠ²ΠΎΠ³ΠΎ списка, Ρ‚ΠΎΠ³Π΄Π° ΠΊΠ°ΠΊ функция scanr помСстит Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Π² ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ элСмСнт.

Π€ΡƒΠ½ΠΊΡ†ΠΈΠΈ сканирования ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ для Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡƒΠ²ΠΈΠ΄Π΅Ρ‚ΡŒ, ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΠΎΠΆΠ½ΠΎ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΊΠ°ΠΊ свёртки. Π”Π°Π²Π°ΠΉΡ‚Π΅ ΠΎΡ‚Π²Π΅Ρ‚ΠΈΠΌ Π½Π° вопрос: ΠΊΠ°ΠΊ ΠΌΠ½ΠΎΠ³ΠΎ ΠΊΠΎΡ€Π½Π΅ΠΉ Π½Π°Ρ‚ΡƒΡ€Π°Π»ΡŒΠ½Ρ‹Ρ… чисСл Π½Π°ΠΌ потрСбуСтся, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΈΡ… сумма прСвысила 1000? Π§Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ сумму ΠΊΠ²Π°Π΄Ρ€Π°Ρ‚ΠΎΠ² Π½Π°Ρ‚ΡƒΡ€Π°Π»ΡŒΠ½Ρ‹Ρ… чисСл, Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡΡ map sqrt [1..]. Π’Π΅ΠΏΠ΅Ρ€ΡŒ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ сумму, ΠΏΡ€ΠΈΠ±Π΅Π³Π½Π΅ΠΌ ΠΊ ΠΏΠΎΠΌΠΎΡ‰ΠΈ свёртки, Π½ΠΎ ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π½Π°ΠΌ интСрСсно Π·Π½Π°Ρ‚ΡŒ, ΠΊΠ°ΠΊ увСличиваСтся сумма, Π±ΡƒΠ΄Π΅ΠΌ Π²Ρ‹Π·Ρ‹Π²Π°Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ scanl1. ПослС Π²Ρ‹Π·ΠΎΠ²Π° scanl1 посмотрим, сколько элСмСнтов Π½Π΅ ΠΏΡ€Π΅Π²Ρ‹ΡˆΠ°ΡŽΡ‚ 1000. ΠŸΠ΅Ρ€Π²Ρ‹ΠΉ элСмСнт Π² Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ Ρ€Π°Π±ΠΎΡ‚Ρ‹ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ scanl1 Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±Ρ‹Ρ‚ΡŒ Ρ€Π°Π²Π΅Π½ Π΅Π΄ΠΈΠ½ΠΈΡ†Π΅. Π’Ρ‚ΠΎΡ€ΠΎΠΉ Π±ΡƒΠ΄Π΅Ρ‚ Ρ€Π°Π²Π΅Π½ 1 плюс ΠΊΠ²Π°Π΄Ρ€Π°Ρ‚Π½Ρ‹ΠΉ ΠΊΠΎΡ€Π΅Π½ΡŒ Π΄Π²ΡƒΡ…. Π’Ρ€Π΅Ρ‚ΠΈΠΉ элСмСнт – это ΠΊΠΎΡ€Π΅Π½ΡŒ Ρ‚Ρ€Ρ‘Ρ… плюс Π²Ρ‚ΠΎΡ€ΠΎΠΉ элСмСнт. Если Ρƒ нас x сумм ΠΌΠ΅Π½ΡŒΡˆΠΈΡ… 1000, Ρ‚ΠΎ Π½Π°ΠΌ ΠΏΠΎΡ‚Ρ€Π΅Π±ΠΎΠ²Π°Π»ΠΎΡΡŒ (x+1) элСмСнтов, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€Π΅Π²Π·ΠΎΠΉΡ‚ΠΈ 1000.