Ru/Monad
From HaskellWiki
(перенесено из статьи введение в Haskell IO)
1 Немного глубже в do
Поначалу кажется, что do - какая-то чёрная магия, или встроенный синтаксис для грязных процедур. На самом деле всё это просто cинтаксический сахар, без которого можно обойтись, но который позволяет склеивать процедуры и делает их написание проще.
Для одного выражения do излишне:
main = do putStr "Привет!"
без do можно записать как:
main = putStr "Привет!"
Как же обойтись без do для нескольких действий?
main = do putStr "Как Вас зовут?" putStr "Сколько Вам лет?" putStr "Неплохой денёк сегодня!"
Тут do говорит, что действия идут одно за другим. Это переводится в оператор последовательности (>>):
main = (putStr "Как Вас зовут?") >> (putStr "Сколько Вам лет?") >> (putStr "Неплохой денёк сегодня!")
Более сложными являются примеры с (<-):
main = do a <- readLn print a
Такой код переводится в:
main = readLn >>= (\a -> print a)
Выражения типа (x >>= (\y -> z)) означает "сделать x, взять его результат, подставить его в лямбду вместо y, вычислить z, и сделать z".
С этим оператором можно писать, к примеру, и так:
main = readLn >>= print
Чтобы закрепить принцип избавления от do, рассмотрим внимательно пример программы в трёх вариантах. Сначала идёт do, потом его перевод со скобками, и под конец - без них, что дозволительно благодаря приоритетам операторов:
main = main3 main1 = do putStr "Как Вас зовут? " i <- readLn putStr "Сколько Вам лет? " v <- readLn putStr "Привет, " putStr i putStr "! Неплохой денёк сегодня!" main2 = (putStr "Как Вас зовут? ") >> readLn >>= ( \i -> ( (putStr "Сколько Вам лет? ") >> readLn >>= ( \v -> ( (putStr "Привет, ") >> (putStr i) >> (putStr "! Неплохой денёк сегодня!") ) ) ) ) main3 = putStr "Как Вас зовут? " >> readLn >>= \i -> putStr "Сколько Вам лет? " >> readLn >>= \v -> putStr "Привет, " >> putStr i >> putStr "! Неплохой денёк сегодня!"
Зачем это всё знать? А все дело в том, что все эти операторы (и do) используются не только в процедурах, а и, к примеру, в списках. Их смысл можно даже переопределять!
Подробнее о списках:
a1 = do x <- [10,100,1000] -- перебрать все эти числа как x y <- [1,2,3] -- перебрать 1..3 как y return (x*y) -- слить (x*y) в список-результат -- Результат: [10,20,30,100,200,300,1000,2000,3000]
2 Ссылки
- (на русском)
