( >>=)
::m a ->(a ->m b) ->m b
( =<<) ::(a ->m b) ->m a ->m b
( =<<) =flip ( >>=)
Вспомним основные производные функции для этих классов:
Или в терминах класса Kleisli:
-- Композиция
( >=>) :: Monadm =>(a ->m b) ->(b ->m c) ->(a ->m c)
( <=<) :: Monadm =>(b ->m c) ->(a ->m b) ->(a ->m c)
-- Константные функции
( *>) :: Applicativef =>f a ->f b ->f b
( <*) :: Applicativef =>f a ->f b ->f a
-- Применение обычных функций к специальным значениям
( <$>)
:: Functorf =>(a ->b) ->f a ->f b
liftA
:: Applicativef =>(a ->b)
->f a ->f b
liftA2 :: Applicativef =>(a ->b ->c)
->f a ->f b ->f c
liftA3 :: Applicativef =>(a ->b ->c ->d) ->f a ->f b ->f c ->f d
-- Преобразование элементов списка специальной функцией
mapM
:: Monadm =>(a ->m b) ->[a] ->m [b]
Нам понадобится модуль с определениями типов и экземпляров монад для всех типов, которые мы рас-
смотрели в предыдущей главе. Экземпляры для []и Maybeуже определены в Prelude, а типы State, Reader
и Writerможно найти в библиотеках mtl и transformers. Пока мы не знаем как устанавливать библиотеки
определим эти типы и экземпляры для Monadсамостоятельно. Возможно вы уже определили их, выполняя
одно из упражнений предыдущей главы, если это так сейчас вы можете сверить ответы. Определим модуль
Types:
module Types(
State( ..), Reader( ..), Writer( ..),
runState, runWriter, runReader,
| 105
module Control.Applicative,
module Control.Monad,
module Data.Monoid)
where
import Data.Monoid
import Control.Applicative
import Control.Monad
-------------------------------------------------
-- Функции с состоянием
--
--
a -> State s b
data States a = State(s ->(a, s))
runState :: States a ->s ->(a, s)
runState ( Statef) =f
instance Monad( States) where
return a
= State $\s ->(a, s)
ma >>=mf = State $\s0 ->
let(b, s1) =runState ma s0
in
runState (mf b) s1
---------------------------------------------------
-- Функции с окружением
--
--
a -> Reader env b
data Readerenv a = Reader(env ->a)
runReader :: Readerenv a ->env ->a
runReader ( Readerf) =f
instance Monad( Readerenv) where
return a
= Reader $const a
ma >>=mf
= Reader $\env ->
letb =runReader ma env
in
runReader (mf b) env
---------------------------------------------------
-- Функции-накопители
--
--
Monoid msg => a -> Writer msg b
data Writermsg a = Writer(a, msg)
deriving( Show)
runWriter :: Writermsg a ->(a, msg)
runWriter ( Writerf) =f
instance Monoidmsg => Monad( Writermsg) where
return a
= Writer(a, mempty)
ma >>=mf
= Writer(c, msgA ‘mappend‘ msgF)
where(b, msgA) =runWriter ma
(c, msgF) =runWriter $mf b
Я пропустил определения для экземпляров классов Functorи Applicative, их можно получить из экзем-
пляра для класса Monadс помощью стандартных функций liftM, return и ap из модуля Control.Monad.
Нам встретилась новая запись в экспорте модуля. Для удобства мы экспортируем модули
Control.Applicative, Control.Monadи Data.Monoidцеликом. Для этого мы написали ключевое слово
moduleперед экспортируемым модулем. Теперь если мы в каком-нибудь другом модуле импортируем
модуль Typesнам станут доступными все функции из этих модулей.
Мы определили экземпляры для Functorи Applicativeс помощью производных функций класса Monad.
106 | Глава 7: Функторы и монады: примеры
7.1 Случайные числа
С помощью монады Stateможно имитировать случайные числа. Мы будем генерировать случайные числа
Читать дальше