Главная » Haskell » Модуль Monad

0

Модуль  Monad содержит  дополнительные расширения  функциональности языка Haskell, которая используется для работы с монадами. Использование модуля:

import  Control.Monad

Данный модуль определяет три класса, которые описывают интерфейсы монадических типов.

Класс:  Functor

Описание: интерфейс для типов, которые могут проецироваться друг на друга.

Определение:

class Functor   f where

fmap :: (a  ->  b)  ->  f  a  ->  f b

Экземпляры класса Functor  должны удовлетворять следующим законам:

fmap id        == id

fmap (f . g)  == fmap f . fmap g

Для  этого класса определены  экземпляры для следующих типов:  Digit, Elem, FingerTree,   IO, Id,  IntMap,  Maybe,  Node, Queue,  ReadP,  ReadPrec, STM, Seq, Tree, ViewL, ViewR, ZipList, [], Array  i, Const m, Either a, Map  k, ST  s, WrappedMonad  m, (,) a, (->) r, WrappedArrow  a  b.

Класс: Monad

Описание: интерфейс для определения базовых операций над монадами, понятием из теории категорий. С точки зрения программиста на языке Haskell о монадах проще всего думать как  об абстрактном типе данных, представляющим последовательность действий.

Определение:

class  Monad  m  where

(>>=)    :: m   a ->  (a  ->  m  b)  ->  m   b (>>)      :: m  a ->  m   b ->  m   b

return :: a ->  m   a

fail  :: String ->  m   a

Для каждого экземпляра класса Monad  достаточно объявить  методы (>>=) и return, хотя другие методы также  можно  определить  в целях оптимизации. Также  любой экземпляр этого  класса должен удовлетворять следующим законам:

return a >>= k

==

k  a

m   >>= return

==

m

m   >>= (\x ->  k  x  >>= h)

==

(m >>= k) >>= h

Если тип одновременно является экземпляром классов Functor  и Monad, то он дополнительно должен удовлетворять следующему правилу:

fmap f xs  == xs  >>= return . f

Операция (>>=) последовательно выполняет два действия, передавая во второе результат выполнения первого действия. Это операция связывания двух действий в последовательность.  Операция (>>) является облегчённой  версией операции (>>=),  которая  используется тогда, когда результат выполнения первого действия не требуется во втором действии.

Метод return втягивает некоторое значение в монаду. Метод fail останавливает процесс последовательного выполнения действий с некоторым сообщением о причине остановки. Последний метод не является частью математического определения монады и введён в класс Monad для того чтобы корректно обрабатывать образцы в выражениях do.

Экземпляром этого класса являются следующие типы данных: IO, Maybe, P,

ReadP, ReadPrec,  STM, Seq, [], ArrowMonad  a, ST  s, (->) r.

Класс:  MonadPlus

Описание: интерфейс для монад, у которых есть единица и которые поддерживают ассоциативную операцию (полугруппы).

Определение:

class Monad  m   => MonadPlus  m   where mzero :: m   a

mplus :: m   a ->  m   a ->  m   a

Любой экземпляр этого класса должен удовлетворять следующим законам:

mzero >>= f  == mzero v  >>  mzero   ==  mzero

Константный метод mzero возвращает единицу ассоциативной операции mplus

полугруппы.

Экземпляром этого класса являются следующие типы  данных:  Maybe, P,

ReadP, ReadPrec, Sec, [].

Утилитарные функции в этом модуле подчиняются некоторым соглашениям о наименовании. Постфикс M  обозначает, что функция  всегда работает с категориями Клейсли. В таких функциях  конструктор типа m  всегда используется только в типах, возвращаемых функциями. Например:

filter ::               (a  ->      Bool)   ->  [a]  ->      [a] filterM :: (Monad m) => (a  ->  m  Bool)  ->  [a] ->  m   [a]

Постфикс (_) используется в функциях, которые  используются  только тогда, когда результат выполнения не важен, а важны только побочные эффекты, предоставляемые монадой. Это значит, что такие  функции меняют тип (m  a) на (m  ()). Например:

sequence   :: Monad  m   => [m a]  ->  m   [a] sequence_ :: Monad  m  => [m a] ->  m   ()

Префикс m обобщает обычную  функцию в функцию, работающую с монадами.

Так, к примеру:

sum  :: Num  a             =>  [a]    ->  a msum  ::  MonadPlus m   => [m a] ->  m   a

Для работы с перечисленными классами определены следующие утилитарные функции.

Функция: mapM

Описание: расширение функции map для работы с категориями Клейсли.

Определение:

mapM  :: Monad  m   => (a  ->  m   b)  ->  [a] ->  m   [b] mapM  f = sequence .  map  f

Функция: mapM-

Описание: вариант функции mapM, используемый тогда, когда результат функции не важен, но важны побочные эффекты монады.

Определение:

mapM_  :: Monad  m   => (a  ->  m   b)  ->  [a] ->  m   () mapM_  f = sequence_ .  map  f

Функция: forM

Описание: вариант функции mapM, у которого входные аргументы следуют в обратном порядке. Используется в эстетических целях.

Определение:

forM  :: Monad  m   => [a] ->  (a  ->  m  b)  ->  m   [b] forM  = flip mapM

Функция: forM-

Описание: вариант функции mapM_, у которого входные аргументы следуют в обратном порядке. Используется в эстетических целях.

Определение:

forM_  :: Monad  m   => [a] ->  (a  ->  m  b)  ->  m   () forM_  = flip mapM_

Функция: sequence

Описание: последовательно исполняет каждое действие слева направо, собирая результат выполнения этих действия и возвращая его.

Определение:

sequence :: Monad  m   => [m a]  ->  m   [a] sequence []     =  return []

sequence (c:cs) = do x   < c

xs  < sequence  cs return  (x:xs)

Функция: sequence-

Описание: вариант функции  sequence, используемый тогда, когда  результат функции не важен, но важны побочные эффекты монады.

Определение:

sequence_ :: Monad  m   => [m a]  ->  m   () sequence_ = foldr  (>>)  (return ())

Функция: (=<<)

Описание: вариант операции (>>=), у которого входные аргументы следуют в обратном порядке. Используется в эстетических целях.

Определение:

(=<<)  :: Monad  m   => (a  ->  m   b)  ->  m  a  ->  m   b f =<< x  = x  >>= f

Функция: join

Описание: функция для развёртывания одного монадического уровня и слияния значений на внутреннем уровне монадической структуры.  Разворачивает одну монаду (результат работы функции должен быть понятен из её сигнатуры). Определение:

join :: Monad  m   => m   (m  a) ->  m   a join x  = x  >>=  id

Функция: msum

Описание: обобщение функции sum (см. стр. 311) для списков на произвольную монаду, у которой имеется единица и операция сложения (ассоциативная операция полугруппы).

Определение:

msum  :: MonadPlus m   =>  [m a] ->  m   a msum  =  foldr  mplus mzero

Функция: filterM

Описание: обобщение функции filter (см. стр. 354) для списков на произвольную монаду.

Определение:

filterM :: Monad  m   => (a  ->  m   Bool)   ->  [a] ->  m   [a] filterM _ []     = return  []

filterM p (x:xs) =  do  flg < p x

ys   < filterM  p xs return  (if flg

then  x:ys else  ys)

Функция: mapAndUnzipM

Описание: функция, которая сочетает в себе эффекты функций map (см. стр. 356) и unzip  (см. стр. 270) для произвольной монады. Функция mapAndUnzip применяет заданную функцию над каждым элементом заданного списка, возвращает пару списков по результату действия входной функции.

Определение:

mapAndUnzipM  :: Monad  m   => (a  ->  m   (b, c)) ->  [a] ->  m  ([b], [c]) mapAndUnzipM  f xs  = sequence (map f xs)  >>= return . unzip

Функция: zipWithM

Описание: обобщает функцию zipWith (см. стр. 269) для списков на произвольную монаду.

Определение:

zipWithM  :: Monad  m   => (a  ->  b ->  m   c) ->  [a] ->  [b] ->  m   [c] zipWithM  f xs  ys  = sequence (zipWith  f  xs  ys)

Функция: zipWith-

Описание: вариант функции  zipWithM,  используемый тогда, когда  результат функции не важен, но важны побочные эффекты монады.

Определение:

zipWithM_  :: Monad  m   => (a  ->  b ->  m   c) ->  [a] ->  [b]  ->  m   () zipWithM_  f xs  ys  = sequence_ (zipWith f xs  ys)

Функция: foldM

Описание:  обобщает функцию foldl (см. стр. 253) для списков на произвольную монаду.

Определение:

foldM  :: Monad  m   => (a  ->  b ->  m   a)  ->  a ->  [b]  ->  m   a foldM  _ a []     = return a

foldM  f a (x:xs) = f a x  >>= \fax ->  foldM  f fax  xs

Необходимо помнить, что эта функция оперирует своими аргументами слева направо. Так, к примеру

foldM  f a1 [x1, x2,  …, xm]

тождественно

do a2 < f a1  x1 a3  < f  a2 x2

f  am  xm

Если необходима свёртка монады справа налево, то входной список следует обратить.

Функция: foldM-

Описание: вариант функции foldM, используемый тогда, когда результат функции не важен, но важны побочные эффекты монады.

Определение:

foldM_  :: Monad  m   => (a  ->  b ->  m   a)  ->  a ->  [b]  ->  m   () foldM_  f a xs  = foldM  f a xs  >> return  ()

Функция: replicateM

Описание: обобщает функцию replicate (см. стр. 259) для списков на  произвольную монаду.

Определение:

replicateM :: Monad  m   => Int ->  m  a ->  m   [a] replicateM n x  =  sequence (replicate n x)

Функция: replicateM-

Описание: вариант функции replicateM, используемый тогда, когда результат функции не важен, но важны побочные эффекты монады.

Определение:

replicateM_ :: Monad  m   => Int ->  m   a ->  m   () replicateM_ n x  =  sequence_ (replicate n x)

Функция: guard

Описание: аналог охраны для произвольной монады, для которой  определена единица и ассоциативная операция полугруппы.

Определение:

guard  :: MonadPlus m   =>  Bool  ->  m   () guard  True    =  return ()

guard  False  = mzero

Функция: when

Описание: исполняет монадическое действие, если первый аргумент равен True.

Определение:

when :: (Monad m) => Bool  ->  m  () ->  m   () when p s  = if p

then  s

else  return ()

Функция: unless

Описание: зеркальный вариант функции when, исполняющий монадическое действие, если первый аргумент равен False.

Определение:

unless  :: (Monad m) => Bool  ->  m  () ->  m   () unless  p s  = if p

then  return  () else  s

Функция: liftM

Описание: втягивает одноаргументную функцию в монаду таким  образом, что результат выполнения функции становится обёрнутым монадой.

Определение:

liftM :: (Monad m) => (a1  ->  r) ->  m  a1  ->  m   r liftM f m1  = do x1 < m1

return (f x1)

Функция: liftM2

Описание: втягивает двухаргументную функцию в монаду таким  образом, что результат выполнения функции становится обёрнутым монадой.

Определение:

liftM2 :: (Monad m) => (a1  ->  a2 ->  r) ->  m   a1 ->  m  a2  ->  m   r liftM2 f m1  m2  = do x1 < m1

x2 < m2

return (f x1 x2)

Функция: liftM3

Описание: втягивает трёхаргументную функцию в монаду таким  образом, что результат выполнения функции становится обёрнутым монадой.

Определение:

liftM3 :: (Monad m) => (a1  ->  a2 ->  a3 ->  r) ->  m   a1 ->  m   a2 ->  m  a3  ->  m   r liftM3 f m1  m2  m3  = do x1 < m1

x2  < m2 x3  < m3

return (f x1 x2 x3)

Функция: liftM4

Описание: втягивает четырёхаргументную функцию в монаду таким  образом, что результат выполнения функции становится обёрнутым монадой. Определение:

liftM4 :: (Monad m) => (a1  ->  a2 ->  a3 ->  a4 ->  r) ->  m   a1 ->  m   a2 ->  m   a3 ->  m  a4  ->  m   r liftM4 f m1  m2  m3  m4  = do x1 < m1

x2  < m2 x3  < m3 x4  < m4

return (f x1  x2  x3 x4)

Функция: liftM5

Описание: втягивает пятиаргументную функцию в монаду таким образом, что результат выполнения функции становится обёрнутым монадой.

Определение:

liftM5 :: (Monad m) => (a1  ->  a2 ->  a3 ->  a4  ->  a5 ->  r)

->  m   a1 ->  m   a2 ->  m   a3 ->  m   a4 ->  m   a5 ->  m   r liftM5 f m1  m2  m3  m4  m5  = do x1 < m1

x2  < m2 x3  < m3 x4  < m4 x5  < m5

return (f x1  x2  x3 x4 x5)

Функция: ap

Описание: во многих случаях функции семейства liftM для  функций разного числа аргументов можно заменить последовательным применением этой функции.

Определение:

ap :: (Monad m) => m   (a  ->  b)  ->  m   a ->  m   b ap = liftM2 id

Например, следующий код

return f ‘ap‘ x1 ‘ap‘  … ‘ap‘ xn

эквивалентен коду

liftMn f  x1 x2 …  xn

Источник: Душкин Р. В., Справочник по языку Haskell. М.: ДМК Пресс, 2008. 544 с., ил.

По теме:

  • Комментарии