![Page 1: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/1.jpg)
ЛЕНИВЫЕ
ВЫЧИСЛЕНИЯ:плюсы и минусы
(RuHaskell.Meetup 2015 Summer, fromGregorian 2015 06 21)
![Page 2: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/2.jpg)
Лучше ничем не заниматься,чем заниматься ничем.
Ď
Тацит
![Page 3: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/3.jpg)
QUI EST QUI
Ħ
![Page 4: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/4.jpg)
Haskell-программа —
совокупность выражений
/англ. expression/
![Page 5: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/5.jpg)
12.3 - 1.09
Это выражение
![Page 6: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/6.jpg)
"/home/dsh" </> "meetup2015"
И это
![Page 7: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/7.jpg)
head [15, 2, 6]
И это
![Page 8: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/8.jpg)
9
И даже это!
![Page 9: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/9.jpg)
Запуск Haskell-программы —
начало вычисления её выражений
/англ. evaluation/
![Page 10: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/10.jpg)
Вычислить выражение —
значит сократить его
/англ. reduce/
![Page 11: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/11.jpg)
В основе сокращения —
применение функции
/англ. function application/
![Page 12: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/12.jpg)
let sum = 2 + 3
Можно сократить
![Page 13: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/13.jpg)
let sum = (+) 2 3
Сокращаем…
![Page 14: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/14.jpg)
let sum = 5
Готово
![Page 15: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/15.jpg)
Если сократить нельзя —
выражение в нормальной форме
/англ. normal form/
![Page 16: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/16.jpg)
Если сократить можно —
выражение называют сокращаемым
/англ. reducible expression или redex/
![Page 17: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/17.jpg)
ПРИНЦИПЫ ЛЕНИ
ȣ
![Page 18: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/18.jpg)
№ 1ȣ
Выражение не сокращается,пока в этом нет необходимости
![Page 19: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/19.jpg)
main :: IO ()
main =
let stupid = 2 `div` 0
in print stupid
Вполне ожидаемая ошибка
![Page 20: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/20.jpg)
main :: IO ()
main =
let stupid = 2 `div` 0
in putStrLn "Just exit!"
Никакой ошибки
![Page 21: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/21.jpg)
№ 2ȣ
Спускаемся настолько,насколько это нужно
![Page 22: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/22.jpg)
main :: IO ()
main =
let some = ( 2 `div` 0
, [2 * 3, 4 `div` 0]
)
(_, second) = some
[elem1, _] = second
in print elem1
Ленивый лифт
![Page 23: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/23.jpg)
ПЛЮСЫ
�
![Page 24: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/24.jpg)
№ 1�
Рациональность
![Page 25: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/25.jpg)
main :: IO ()
main = do
file <- readFile "/home/dsh/big.log"
putStrLn $ take 100 file
Читаем лишь то, что нужно
![Page 26: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/26.jpg)
№ 2�
Бесконечность
![Page 27: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/27.jpg)
head :: [a] -> ahead (x:_) = x
Возвращаем первый элемент списка
![Page 28: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/28.jpg)
main :: IO ()
main =
print $ head [1, 10, 100]
Причём как конечного списка…
![Page 29: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/29.jpg)
main :: IO ()
main =
print $ head [1..]
… так и бесконечного
![Page 30: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/30.jpg)
№ 3�
DSL
![Page 31: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/31.jpg)
selectBy :: Bool -> (a, a) -> aselectBy True (f, _) = fselectBy False (_, s) = s
Замена условной конструкции
![Page 32: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/32.jpg)
import System.Exit
main :: IO ()
main = do
putStrLn "Input web prefix:"
prefix <- getLine
selectBy (prefix == "https")
( putStrLn "secure web :)"
, exitWith $ ExitFailure 1
)
И это честная замена!
![Page 33: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/33.jpg)
МИНУСЫ
�
![Page 34: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/34.jpg)
№ 1�
Неожиданное поведение
![Page 35: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/35.jpg)
import Data.String.Utils
main :: IO ()
main = do
file <- readFile path
writeFile path $ replace "," ";" file
where path = "/home/dsh/data"
Ну-ну…
![Page 36: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/36.jpg)
openFile: resource busy (file is locked)
Лень мешает
![Page 37: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/37.jpg)
import Data.String.Utils
import qualified System.IO.Strict as S
main :: IO ()
main = do
file <- S.readFile path
writeFile path $ replace "," ";" file
where path = "/home/dsh/data"
Строгость решает
![Page 38: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/38.jpg)
Выход:
Не игнорируйте слова
strictly и lazily
в документации
![Page 39: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/39.jpg)
№ 2�
Space Leak
![Page 40: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/40.jpg)
Не путать с Memory Leak!
![Page 41: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/41.jpg)
Memory Leak —
низкоуровневая ошибкауправления памятью
�
![Page 42: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/42.jpg)
Space Leak —
высокоуровневая ошибкапроектирования
Ǘ
![Page 43: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/43.jpg)
main :: IO ()
main =
let stupid = 2 `div` 0
in putStrLn "Just exit!"
Деления не было
![Page 44: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/44.jpg)
2 `div` 0
Невычисленное (отложенное) выражение
/англ. unevaluated expression или thunk/
![Page 45: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/45.jpg)
Все отложенные выражения
живут в памяти
Thank you Cap!
![Page 46: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/46.jpg)
Проблема в их количестве!
DZ
![Page 47: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/47.jpg)
f :: Num b => [a] -> b -> bf [] c = cf (_:xs) c = f xs $ c + 1
Пустышка с большой проблемой
![Page 48: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/48.jpg)
f [1,2,3] 0
Применяем…
![Page 49: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/49.jpg)
f 1:[2,3] 0 + 1
Первый шаг…
![Page 50: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/50.jpg)
f 1:2:[3] (0 + 1) + 1
Второй шаг…
![Page 51: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/51.jpg)
f 1:2:3:[] ((0 + 1) + 1) + 1
Третий шаг…
![Page 52: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/52.jpg)
f [] ((0 + 1) + 1) + 1
Последний шаг…
![Page 53: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/53.jpg)
((0 + 1) + 1) + 1 = 3
Готово
![Page 54: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/54.jpg)
Ленивый вариант
main :: IO ()
main =
let v = f [1..50000000] (0 :: Integer)
in print v
Время: 62 с
Память: 6.19 ГБ
2
ǯ
![Page 55: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/55.jpg)
f' :: Num b => [a] -> b -> bf' [] c = cf' (_:xs) c = f' xs $! c + 1
Пустышка без проблем
![Page 56: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/56.jpg)
Строгий вариант
main :: IO ()
main =
let v = f' [1..50000000] (0 :: Integer)
in print v
Время: 4 с
Память: мизерная
2
ǯ
![Page 57: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/57.jpg)
Выход:
Если код может раздуться,разбавьте лень строгостью
![Page 58: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/58.jpg)
main :: IO ()
main =
print $ Laziness good bad
where good = [ "Рациональность"
, "Бесконечность"
, "DSL"
]
bad = [ "Неожиданное поведение"
, "Space Leak"
]
![Page 59: Ленивые вычисления: плюсы и минусы. Денис Шевченко](https://reader030.vdocuments.pub/reader030/viewer/2022020106/55cca900bb61ebca4c8b465a/html5/thumbnails/59.jpg)
Благодарю за внимание!
Денис Шевченко
dshevchenko.biz¢