Difference between revisions of "Ru/Monad"

From HaskellWiki
< Ru
Jump to navigation Jump to search
(перенесено из статьи Ru/IO)
 
m
 
(One intermediate revision by one other user not shown)
Line 92: Line 92:
 
</haskell>
 
</haskell>
   
  +
== Ссылки ==
Но об этих тонкостях лучше прочитать в статье [[Ru/Monad | о монадах]].
 
  +
* (''на русском'')
  +
** [http://rsdn.ru/article/haskell/haskell_part2.xml#E1JAC Мягкое введение в Haskell. Часть 9: О Монадах]
  +
** [http://ru.wikibooks.org/wiki/%D0%9E%D1%81%D0%BD%D0%BE%D0%B2%D1%8B_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F/%D0%9C%D0%BE%D0%B4%D1%83%D0%BB%D0%B8_%D0%B8_%D0%BC%D0%BE%D0%BD%D0%B0%D0%B4%D1%8B_%D0%B2_Haskell%27%D0%B5#.D0.9C.D0.BE.D0.BD.D0.B0.D0.B4.D1.8B Основы функционального программирования/Монады в Haskell'е]
  +
  +
[[Category:Ru]]

Latest revision as of 14:24, 4 April 2012

(перенесено из статьи введение в Haskell IO)

Немного глубже в 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]

Ссылки