html текст
All interests
  • All interests
  • Design
  • Food
  • Gadgets
  • Humor
  • News
  • Photo
  • Travel
  • Video
Click to see the next recommended page
Like it
Don't like
Add to Favorites

Тройка полезных монад перевод

Внимание: перед тем как читать текст ниже, вы уже должны иметь представление о том, что такое монады. Если это не так, то прежде прочитайте вот этот пост!

Перед нами функция half:


И мы можем применить её несколько раз:
half . half $ 8
=> 2


Всё работает как и ожидалось. Но вот вы решили, что хорошо бы иметь лог того, что происходит с этой функцией:


half x = (x `div` 2, "Я только что располовинил  " ++ (show x) ++ "!")


Что ж, отлично. Но что будет если вы теперь захотите применить half несколько раз?
half . half $ 8


Вот то, что мы хотели бы, чтобы происходило:



Спойлер: автоматически так не сделается. Придётся всё расписывать ручками:
finalValue = (val2, log1 ++ log2)
    where (val1, log1) = half 8
          (val2, log2) = half val1


Фу! Это ни капли не похоже на лаконичное
half . half $ 8


А что, если у вас есть ещё функции, имеющие лог? Напрашивается такая схема: для каждой функции, возвращающей вместе со значением лог, мы бы хотели объединять эти логи. Это побочный эффект, а никто не силён в побочных эффектах так, как монады!

Монада Writer



Появляется монада Writer на белом коне
Монада Writer — крутая личность. «Не парься, чувак, я обработаю твои логи,» — говорит она. — «Возвращайся к своему чистому коду и выжми максимум под что-нибудь из Zeppelin!»

У каждого экземпляра Writer есть лог и возвращаемое значение:


data Writer w a = Writer { runWriter :: (a, w) }


Writer позволяет нам писать код наподобие
half 8 >>= half


Ну, или вы можете использовать <=< функцию, которая суть композиция функций для монад, чтобы получить:
half <=< half $ 8

что чертовски близко к half . half $ 8. Круто!

Вы можете использовать tell, чтобы записать что-то в лог. А return передаст это значение в Writer. Вот наша обновлённая функция half:
half :: Int -> Writer String Int
half x = do
        tell ("I just halved " ++ (show x) ++ "!")
        return (x `div` 2)


Она возвращает Writer:


И мы можем использовать runWriter, чтобы извлечь из него значение:


runWriter $ half 8
=> (4, "I just halved 8!")


Но самый клёвый момент, это то, что теперь мы можем связать вызовы half в цепочку, используя >>=:
runWriter $ half 8 >>= half
=> (2, "I just halved 8!I just halved 4!")


Вот что происходит:



Магическим образом >>= знает, как объединить два Writer'а, так что нам нет нужды писать самостоятельно какой бы то ни было нудный код! Вот полное определение >>=:



Точно такой же шаблонный код мы ранее писали сами, а теперь эту обязанность взяла на себя >>=. Клёво! Мы так же используем функцию return, которая принимает значение и помещает его в монаду:


return val = Writer (val, "")


(Замечание: это определение почти верное. На самом деле монада Writer позволяет нам использовать любой Monoid в качестве лога, а не одни только строки. Я тут упростил слегка.)

Спасибо тебе, монада Writer!

Монада Reader


Допустим, вы хотите передать какие-то настройки в множество функций. Просто используйте монаду Reader:


Она позволит вам передать ваше значение всем функциям, скрыв сам механизм передачи за кулисами. Например:
greeter :: Reader String String
greeter = do
    name <- ask
    return ("hello, " ++ name ++ "!")


greeter возвращает монаду Reader:


Вот её определение:
data Reader r a = Reader {  runReader :: r -> a }


Reader всегда был перебежчиком. Тёмной лошадкой. Reader другой, потому что он позволяет нам обрабатывать функцию, что смущает при его рассмотрении. Но мы с вами понимаем, что можем использовать runReader, чтобы извлечь эту функцию:


И можем передать этой функции некое состояние, которое потом используется в greeter:



runReader greeter $ "adit"
=> "hello, adit!" 


таким образом, когда вы используете >>=, назад вы должны получить Reader. Когда вы передадите в него состояние, то оно будет передано всем функциям, содержащимся в этой монаде.



m >>= k  = Reader $ \r -> runReader (k (runReader m r)) r


Reader всегда был несколько комплексным. Это вообще его лучшее качество.
return помещает значение в Reader:


return a = Reader $ \_ -> a


И, наконец, ask возвращает вам обратно состояние, которое вы передали:
ask = Reader $ \x -> x 


Хотите провести с Reader'ом больше времени? Врубите панк-рок и взгляните на более длинный пример.

Монада State


Монада State — это более впечатлительный лучший друг монады Reader:


Она в точности тоже самое, что и монада Reader, но с её помощью вы можете не только читать, но и писать!
Вот определение State:
State s a = State { runState :: s -> (a, s) } 





Вы можете получить состояние с помощью get или изменить его с помощью put. Вот пример:
greeter :: State String String
greeter = do
    name <- get
    put "tintin"
    return ("hello, " ++ name ++ "!")


runState greeter $ "adit"
=> ("hello, adit!", "tintin")


Мило! Если Reader был с характером«тебе-меня-не-изменить», то State наоборот стремится к отношениям и сама готова меняться.
Определение State монады выглядит очень похоже на определение монады Reader:
return:


return a = State $ \s -> (a, s)


>>=:



m >>= k = State $ \s -> let (a, s') = runState m s
                         in runState (k a) s'


Заключение





Writer. Reader. State. Сегодня вы добавили три мощных оружия в свой Haskell-арсенал. Используйте их с умом.

От переводчика: я буду бесконечно признательна за любые замечания в личку, которые помогут улучшить качество этого перевода.
Читать дальше
Twitter
Одноклассники
Мой Мир

материал с habrahabr.ru

2

      Add

      You can create thematic collections and keep, for instance, all recipes in one place so you will never lose them.

      No images found
      Previous Next 0 / 0
      500
      • Advertisement
      • Animals
      • Architecture
      • Art
      • Auto
      • Aviation
      • Books
      • Cartoons
      • Celebrities
      • Children
      • Culture
      • Design
      • Economics
      • Education
      • Entertainment
      • Fashion
      • Fitness
      • Food
      • Gadgets
      • Games
      • Health
      • History
      • Hobby
      • Humor
      • Interior
      • Moto
      • Movies
      • Music
      • Nature
      • News
      • Photo
      • Pictures
      • Politics
      • Psychology
      • Science
      • Society
      • Sport
      • Technology
      • Travel
      • Video
      • Weapons
      • Web
      • Work
        Submit
        Valid formats are JPG, PNG, GIF.
        Not more than 5 Мb, please.
        30
        surfingbird.ru/site/
        RSS format guidelines
        500
        • Advertisement
        • Animals
        • Architecture
        • Art
        • Auto
        • Aviation
        • Books
        • Cartoons
        • Celebrities
        • Children
        • Culture
        • Design
        • Economics
        • Education
        • Entertainment
        • Fashion
        • Fitness
        • Food
        • Gadgets
        • Games
        • Health
        • History
        • Hobby
        • Humor
        • Interior
        • Moto
        • Movies
        • Music
        • Nature
        • News
        • Photo
        • Pictures
        • Politics
        • Psychology
        • Science
        • Society
        • Sport
        • Technology
        • Travel
        • Video
        • Weapons
        • Web
        • Work

          Submit

          Thank you! Wait for moderation.

          Тебе это не нравится?

          You can block the domain, tag, user or channel, and we'll stop recommend it to you. You can always unblock them in your settings.

          • habrahabr.ru
          • домен habrahabr.ru

          Get a link

          Спасибо, твоя жалоба принята.

          Log on to Surfingbird

          Recover
          Sign up

          or

          Welcome to Surfingbird.com!

          You'll find thousands of interesting pages, photos, and videos inside.
          Join!

          • Personal
            recommendations

          • Stash
            interesting and useful stuff

          • Anywhere,
            anytime

          Do we already know you? Login or restore the password.

          Close

          Add to collection

             

            Facebook

            Ваш профиль на рассмотрении, обновите страницу через несколько секунд

            Facebook

            К сожалению, вы не попадаете под условия акции