Control.Monad
| Авторское право | (c) Университет Глазго, 2001 |
|---|---|
| Лицензия | В стиле BSD (см. файл libraries/base/LICENSE) |
| Сопровождающий | libraries@haskell.org |
| Стабильность | предварительная |
| Переносимость | переносимый |
| Безопасный Haskell | Безопасный |
| Язык | Haskell2010 |
Классы функторов и монад
class Functor (f :: Type -> Type) where Источник
Тип f является функтором, если он предоставляет функцию fmap, которая для любых типов a и b позволяет применить любую функцию из (a -> b), чтобы преобразовать f a в f b, сохраняя структуру f. Кроме того, f должен удовлетворять следующим законам:
Обратите внимание: второй закон следует из свободной теоремы для типа fmap и первого закона, поэтому достаточно проверить выполнение первого условия. Объяснение можно найти в этих статьях на School of Haskell или у Дэвида Лупошчински.
Минимальное полное определение
Методы
fmap :: (a -> b) -> f a -> f b Источник
fmap используется для применения функции типа (a -> b) к значению типа f a, где f — функтор, чтобы получить значение типа f b. Обратите внимание, что для любого конструктора типов с более чем одним параметром (например, Either) с помощью fmap можно изменить только последний параметр типа (например, b в Either a b).
Для некоторых конструкторов типов с двумя или более параметрами существует экземпляр Bifunctor, позволяющий выполнять отображение как по последнему, так и по предпоследнему параметру.
Примеры
Преобразование Maybe Int в Maybe String с помощью show:
>>> fmap show Nothing Nothing >>> fmap show (Just 3) Just "3"
Преобразование Either Int Int в Either Int String с помощью show:
>>> fmap show (Left 17) Left 17 >>> fmap show (Right 17) Right "17"
Удвоение каждого элемента списка:
>>> fmap (*2) [1,2,3] [2,4,6]
Применение even ко второму элементу пары:
>>> fmap even (2,2) (2,True)
Может показаться удивительным, что функция применяется только к последнему элементу кортежа, тогда как в приведённом выше примере со списком она применяется ко всем элементам списка. Чтобы понять причину, вспомните, что кортежи — это конструкторы типов с несколькими параметрами типа: кортеж из 3 элементов (a,b,c) также можно записать как (,,) a b c, а его экземпляр Functor определён для Functor ((,,) a b) (то есть только третий параметр можно свободно изменять с помощью fmap).
Это объясняет, почему fmap можно использовать с кортежами, содержащими значения разных типов, как в следующем примере:
>>> fmap even ("hello", 1.0, 4)
("hello",1.0,True)
(<$) :: a -> f b -> f a infixl 4 Источник
Заменяет все значения во входных данных одним и тем же значением. Определение по умолчанию — fmap . const, но его можно заменить более эффективной версией.
Примеры
Экземпляры
| Functor Complex Источник | Начиная с: base-4.9.0.0 |
| Functor First Источник | Начиная с: base-4.9.0.0 |
| Functor Last Источник | Начиная с: base-4.9.0.0 |
| Functor Max Источник | Начиная с: base-4.9.0.0 |
| Functor Min Источник | Начиная с: base-4.9.0.0 |
| Functor ArgDescr Источник | Начиная с: base-4.7.0.0 |
| Functor ArgOrder Источник | Начиная с: base-4.7.0.0 |
| Functor OptDescr Источник | Начиная с: base-4.7.0.0 |
| Functor NonEmpty Источник | Начиная с: base-4.9.0.0 |
| Functor STM Источник | Начиная с: base-4.3.0.0 |
| Functor Handler Источник | Начиная с: base-4.6.0.0 |
| Functor Identity Источник | Начиная с: base-4.8.0.0 |
| Functor First Источник | Начиная с: base-4.8.0.0 |
| Functor Last Источник | Начиная с: base-4.8.0.0 |
| Functor Down Источник | Начиная с: base-4.11.0.0 |
| Functor Dual Источник | Начиная с: base-4.8.0.0 |
| Functor Product Источник | Начиная с: base-4.8.0.0 |
| Functor Sum Источник | Начиная с: base-4.8.0.0 |
| Functor ZipList Источник | Начиная с: base-2.1 |
| Functor NoIO Источник | Начиная с: base-4.8.0.0 |
| Functor Par1 Источник | Начиная с: base-4.9.0.0 |
| Functor GenClosure Источник | |
| Functor (StateL s) Источник | Начиная с: base-4.0 |
| Functor (StateR s) Источник | Начиная с: base-4.0 |
| Functor (Proxy :: Type -> Type) Источник | Начиная с: base-4.7.0.0 |
| Functor (U1 :: Type -> Type) Источник | Начиная с: base-4.9.0.0 |
| Functor (V1 :: Type -> Type) Источник | Начиная с: base-4.9.0.0 |
| Functor (ST s) Источник | Начиная с: base-2.1 |
| Functor ((,) a) Источник | Начиная с: base-2.1 |
Определено в GHC.Internal.Base | |
| Arrow a => Functor (WrappedArrow a b) Источник | Начиная с: base-2.1 |
Определено в Control.Applicative Методыfmap :: (a0 -> b0) -> WrappedArrow a b a0 -> WrappedArrow a b b0 Источник (<$) :: a0 -> WrappedArrow a b b0 -> WrappedArrow a b a0 Источник | |
| Functor m => Functor (Kleisli m a) Источник | Начиная с: base-4.14.0.0 |
| Functor (Const m :: Type -> Type) Источник | Начиная с: base-2.1 |
| Monad m => Functor (StateT s m) Источник | Начиная с: base-4.18.0.0 |
| Functor f => Functor (Ap f) Источник | Начиная с: base-4.12.0.0 |
| Functor f => Functor (Alt f) Источник | Начиная с: base-4.8.0.0 |
| (Generic1 f, Functor (Rep1 f)) => Functor (Generically1 f) Источник | Начиная с: base-4.17.0.0 |
Определено в GHC.Internal.Generics Методыfmap :: (a -> b) -> Generically1 f a -> Generically1 f b Источник (<$) :: a -> Generically1 f b -> Generically1 f a Источник | |
| Functor f => Functor (Rec1 f) Источник | Начиная с: base-4.9.0.0 |
| Functor (URec (Ptr ()) :: Type -> Type) Источник | Начиная с: base-4.9.0.0 |
| Functor (URec Char :: Type -> Type) Источник | Начиная с: base-4.9.0.0 |
| Functor (URec Double :: Type -> Type) Источник | Начиная с: base-4.9.0.0 |
| Functor (URec Float :: Type -> Type) Источник | Начиная с: base-4.9.0.0 |
| Functor (URec Int :: Type -> Type) Источник | Начиная с: base-4.9.0.0 |
| Functor (URec Word :: Type -> Type) Источник | Начиная с: base-4.9.0.0 |
| Functor ((,,) a b) Источник | Начиная с: base-4.14.0.0 |
Определён в GHC.Internal.Base | |
| (Functor f, Functor g) => Functor (Product f g) Источник | Начиная с: base-4.9.0.0 |
| (Functor f, Functor g) => Functor (Sum f g) Источник | Начиная с: base-4.9.0.0 |
| (Functor f, Functor g) => Functor (f :*: g) Источник | Начиная с: base-4.9.0.0 |
| (Functor f, Functor g) => Functor (f :+: g) Источник | Начиная с: base-4.9.0.0 |
| Functor (K1 i c :: Type -> Type) Источник | Начиная с: base-4.9.0.0 |
| Functor ((,,,) a b c) Источник | Начиная с: base-4.14.0.0 |
Определён в GHC.Internal.Base | |
| Functor ((->) r) Источник | Начиная с: base-2.1 |
Определён в GHC.Internal.Base | |
| (Functor f, Functor g) => Functor (Compose f g) Источник | Начиная с: base-4.9.0.0 |
| (Functor f, Functor g) => Functor (f :.: g) Источник | Начиная с: base-4.9.0.0 |
| Functor f => Functor (M1 i c f) Источник | Начиная с: base-4.9.0.0 |
| Functor ((,,,,) a b c d) Источник | Начиная с: base-4.18.0.0 |
Определён в GHC.Internal.Base | |
| Functor ((,,,,,) a b c d e) Источник | Начиная с: base-4.18.0.0 |
Определён в GHC.Internal.Base | |
| Functor ((,,,,,,) a b c d e f) Источник | Начиная с: base-4.18.0.0 |
Определён в GHC.Internal.Base | |
class Applicative m => Monad (m :: Type -> Type) where Источник
Класс Monad определяет базовые операции над монадой — понятием из раздела математики, известного как теория категорий. Однако с точки зрения программиста на Haskell лучше всего рассматривать монаду как абстрактный тип данных, представляющий действия. Выражения do в Haskell предоставляют удобный синтаксис для записи монадических выражений.
Экземпляры Monad должны удовлетворять следующим законам:
- Левая единица
return a >>= k = k a- Правая единица
m >>= return = m- Ассоциативность
m >>= (\x -> k x >>= h) = (m >>= k) >>= h
Кроме того, операции Monad и Applicative должны соотноситься следующим образом:
Из приведённых выше законов следуют:
а также то, что pure и (<*>) удовлетворяют законам аппликативного функтора.
Экземпляры Monad для List, Maybe и IO, определённые в Prelude, удовлетворяют этим законам.
Минимальное полное определение
Методы
(>>=) :: m a -> (a -> m b) -> m b infixl 1 Источник
Последовательно объединяет два действия, передавая значение, полученное в результате первого, в качестве аргумента второму.
'as >>= bs' можно понимать как выражение do
do a <- as bs a
Альтернативное название этой функции — 'bind', но некоторые называют её 'flatMap'; это название связано с тем, что функция эквивалентна
\x f -> join (fmap f x) :: Monad m => m a -> (a -> m b) -> m b
что можно рассматривать как отображение значения с помощью Monad m => m a -> m (m b), а затем «сведение» m (m b) к m b с помощью join.
(>>) :: m a -> m b -> m b infixl 1 Источник
Последовательно объединяет два действия, отбрасывая значение, полученное в результате первого, подобно операторам последовательного выполнения (например, точке с запятой) в императивных языках.
'as >> bs' можно понимать как выражение do
do as bs
или через (>>=) как
as >>= const bs
Внедряет значение в монадический тип. Эта функция не должна отличаться от своей реализации по умолчанию в виде pure. Существование этой функции объясняется лишь историческими причинами.
Экземпляры
| Monad P Источник | С версии: base-2.1 |
| Monad ReadP Источник | С версии: base-2.1 |
| Monad ReadPrec Источник | С версии: base-2.1 |
| Monad IO Источник | С версии: base-2.1 |
| Monad Maybe Источник | С версии: base-2.1 |
| Monad Solo Источник | С версии: base-4.15 |
| Monad [] Источник | С версии: base-2.1 |
| Monad m => Monad (WrappedMonad m) Источник | С версии: base-4.7.0.0 |
Определено в Control.Applicative Методы(>>=) :: WrappedMonad m a -> (a -> WrappedMonad m b) -> WrappedMonad m b Источник (>>) :: WrappedMonad m a -> WrappedMonad m b -> WrappedMonad m b Источник return :: a -> WrappedMonad m a Источник | |
| ArrowApply a => Monad (ArrowMonad a) Источник | С версии: base-2.1 |
Определено в GHC.Internal.Control.Arrow Методы(>>=) :: ArrowMonad a a0 -> (a0 -> ArrowMonad a b) -> ArrowMonad a b Источник (>>) :: ArrowMonad a a0 -> ArrowMonad a b -> ArrowMonad a b Источник return :: a0 -> ArrowMonad a a0 Источник | |
| Monad (ST s) Источник | С версии: base-2.1 |
| Monad (Either e) Источник | С версии: base-4.4.0.0 |
| Monad (Proxy :: Type -> Type) Источник | С версии: base-4.7.0.0 |
| Monad (U1 :: Type -> Type) Источник | С версии: base-4.9.0.0 |
| Monad (ST s) Источник | С версии: base-2.1 |
| Monoid a => Monad ((,) a) Источник | С версии: base-4.9.0.0 |
| Monad m => Monad (Kleisli m a) Источник | С версии: base-4.14.0.0 |
| Monad m => Monad (StateT s m) Источник | С версии: base-4.18.0.0 |
| Monad f => Monad (Ap f) Источник | С версии: base-4.12.0.0 |
| Monad f => Monad (Alt f) Источник | С версии: base-4.8.0.0 |
| Monad f => Monad (Rec1 f) Источник | С версии: base-4.9.0.0 |
| (Monoid a, Monoid b) => Monad ((,,) a b) Источник | С версии: base-4.14.0.0 |
| (Monad f, Monad g) => Monad (Product f g) Источник | С версии: base-4.9.0.0 |
| (Monad f, Monad g) => Monad (f :*: g) Источник | С версии: base-4.9.0.0 |
| (Monoid a, Monoid b, Monoid c) => Monad ((,,,) a b c) Источник | С версии: base-4.14.0.0 |
| Monad ((->) r) Источник | С версии: base-2.1 |
| Monad f => Monad (M1 i c f) Источник | С версии: base-4.9.0.0 |
class Monad m => MonadFail (m :: Type -> Type) where Источник
Если значение связывается в нотации do, шаблон в левой части <- может не совпасть. В этом случае данный класс предоставляет функцию для обработки такой ситуации.
Monad без экземпляра MonadFail можно использовать только с шаблонами, которые всегда совпадают, например с newtype-типами, кортежами, типами данных с единственным конструктором данных и нестрогими шаблонами (~pat).
Экземпляры MonadFail должны удовлетворять следующему закону: fail s должен быть левым нулём для >>=,
fail s >>= f = fail s
Если ваш Monad также является MonadPlus, популярным определением будет
fail _ = mzero
fail s должно быть действием, выполняемым в самой монаде, а не исключением (за исключением экземпляров MonadIO). В частности, fail не следует реализовывать через error.
С версии: base-4.9.0.0
Методы
fail :: HasCallStack => String -> m a Источник
Экземпляры
class (Alternative m, Monad m) => MonadPlus (m :: Type -> Type) where Источник
Монады, которые также поддерживают выбор и отказ.
Минимальное полное определение
Nothing
Экземпляры
| MonadPlus STM Источник |
Выполняет первое действие Начиная с: base-4.3.0.0 |
| MonadPlus P Источник | Начиная с: base-2.1 |
Определён в GHC.Internal.Text.ParserCombinators.ReadP | |
| MonadPlus ReadP Источник | Начиная с: base-2.1 |
| MonadPlus ReadPrec Источник | Начиная с: base-2.1 |
| MonadPlus IO Источник |
Возвращает результат первого действия Начиная с: base-4.9.0.0 |
| MonadPlus Maybe Источник |
Выбирает самое левое значение Начиная с: base-2.1 |
| MonadPlus [] Источник |
Объединяет списки конкатенацией, начиная с пустого списка. Начиная с: base-2.1 |
Определён в GHC.Internal.Base | |
| (ArrowApply a, ArrowPlus a) => MonadPlus (ArrowMonad a) Источник | Начиная с: base-4.6.0.0 |
Определён в GHC.Internal.Control.Arrow Методыmzero :: ArrowMonad a a0 Источник mplus :: ArrowMonad a a0 -> ArrowMonad a a0 -> ArrowMonad a a0 Источник | |
| MonadPlus (Proxy :: Type -> Type) Источник | Начиная с: base-4.9.0.0 |
| MonadPlus (U1 :: Type -> Type) Источник | Начиная с: base-4.9.0.0 |
| MonadPlus m => MonadPlus (Kleisli m a) Источник | Начиная с: base-4.14.0.0 |
| MonadPlus f => MonadPlus (Ap f) Источник | Начиная с: base-4.12.0.0 |
| MonadPlus f => MonadPlus (Alt f) Источник | Начиная с: base-4.8.0.0 |
| MonadPlus f => MonadPlus (Rec1 f) Источник | Начиная с: base-4.9.0.0 |
| (MonadPlus f, MonadPlus g) => MonadPlus (Product f g) Источник | Начиная с: base-4.9.0.0 |
| (MonadPlus f, MonadPlus g) => MonadPlus (f :*: g) Источник | Начиная с: base-4.9.0.0 |
| MonadPlus f => MonadPlus (M1 i c f) Источник | Начиная с: base-4.9.0.0 |
Функции
Соглашения об именовании
Функции этого модуля используют следующие соглашения об именовании:
- Постфикс '
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' обобщает существующую функцию до монадической формы. Например:
filter :: (a -> Bool) -> [a] -> [a] mfilter :: MonadPlus m => (a -> Bool) -> m a -> m a
mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b) Источник
Преобразует каждый элемент структуры в монадическое действие, выполняет эти действия слева направо и собирает результаты. Версию, игнорирующую результаты, см. в mapM_.
Примеры
mapM — это буквально traverse с сигнатурой типа, ограниченной до Monad. Благодаря дополнительным возможностям Monad его реализация может быть эффективнее.
mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m () Источник
Преобразует каждый элемент структуры в монадическое действие, выполняет эти действия слева направо и игнорирует результаты. Версию, которая не игнорирует результаты, см. в mapM.
mapM_ похожа на traverse_, но специализирована для монадических действий.
forM :: (Traversable t, Monad m) => t a -> (a -> m b) -> m (t b) Источник
forM — это mapM с переставленными аргументами. Версию, игнорирующую результаты, см. в forM_.
forM_ :: (Foldable t, Monad m) => t a -> (a -> m b) -> m () Источник
forM_ — это mapM_ с переставленными аргументами. Версию, которая не игнорирует результаты, см. в forM.
forM_ похожа на for_, но специализирована для монадических действий.
sequence :: (Traversable t, Monad m) => t (m a) -> m (t a) Источник
Выполняет каждое монадическое действие в структуре слева направо и собирает результаты. Версию, игнорирующую результаты, см. в sequence_.
Примеры
Базовое использование:
В первых двух примерах вход и выход sequence изоморфны.
>>> sequence $ Right [1,2,3,4] [Right 1,Right 2,Right 3,Right 4]
>>> sequence $ [Right 1,Right 2,Right 3,Right 4] Right [1,2,3,4]
Следующие примеры демонстрируют поведение с коротким замыканием для sequence.
>>> sequence $ Left [1,2,3,4] Left [1,2,3,4]
>>> sequence $ [Left 0, Right 1,Right 2,Right 3,Right 4] Left 0
sequence_ :: (Foldable t, Monad m) => t (m a) -> m () Исходный код
Выполняет каждое монадическое действие в структуре слева направо и игнорирует результаты. Версию, которая не игнорирует результаты, см. в sequence.
sequence_ работает так же, как sequenceA_, но специализирована для монадических действий.
(=<<) :: Monad m => (a -> m b) -> m a -> m b infixr 1 Исходный код
То же, что и >>=, но аргументы переставлены местами.
as >>= f == f =<< as
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c infixr 1 Исходный код
Композиция стрелок Kleisli слева направо.
'(bs >=> cs) a' можно понимать как выражение do
do b <- bs a cs b
или в терминах (>>=) как
bs a >>= cs
(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c infixr 1 Исходный код
Композиция стрелок Клейсли справа налево. (>=>), аргументы переставлены местами.
Обратите внимание, что этот оператор похож на композицию функций (.):
(.) :: (b -> c) -> (a -> b) -> a -> c (<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
forever :: Applicative f => f a -> f b Исходный код
Повторяет действие бесконечно.
Примеры
Часто forever используют для обработки входных данных из сетевых сокетов, Handle и каналов (например, MVar и Chan).
Например, вот как можно реализовать эхо-сервер, используя forever и для прослушивания подключений клиентов через сетевой сокет, и для отправки клиентского ввода обратно через дескрипторы подключений:
echoServer :: Socket -> IO () echoServer socket = forever $ do client <- accept socket forkFinally (echo client) (\_ -> hClose client) where echo :: Handle -> IO () echo client = forever $ hGetLine client >>= hPutStrLn client
Обратите внимание, что «forever» не обязательно означает бесконечное выполнение. Если действие выполняется в MonadPlus и прерывается после некоторого числа итераций, то forever фактически возвращает mzero, тем самым прерывая выполнение вызывающего кода.
void :: Functor f => f a -> f () Исходный код
void value отбрасывает или игнорирует результат вычисления, например возвращаемое значение действия IO.
Примеры
Заменить содержимое Maybe Int на unit:
>>> void Nothing Nothing
>>> void (Just 3) Just ()
Заменить содержимое Either Int Int на unit, получив Either Int ():
>>> void (Left 8675309) Left 8675309
>>> void (Right 8675309) Right ()
Заменить каждый элемент списка на unit:
>>> void [1,2,3] [(),(),()]
Заменить второй элемент пары на unit:
>>> void (1,2) (1,())
Отбросить результат действия IO:
>>> mapM print [1,2] 1 2 [(),()]
>>> void $ mapM print [1,2] 1 2
Обобщения функций для списков
join :: Monad m => m (m a) -> m a Исходный код
Функция join — общепринятый оператор соединения монад. Он используется для удаления одного уровня монадической структуры, перенося связанный аргумент на внешний уровень.
'join bss' можно понимать как выражение do
do bs <- bss bs
Примеры
>>> join [[1, 2, 3], [4, 5, 6], [7, 8, 9]] [1,2,3,4,5,6,7,8,9]
>>> join (Just (Just 3)) Just 3
Часто join используют для запуска вычисления IO, возвращённого транзакцией STM, поскольку транзакции STM не могут напрямую выполнять IO. Напомним, что
atomically :: STM a -> IO a
используется для атомарного выполнения транзакций STM. Поэтому, специализировав типы atomically и join до
atomically :: STM (IO b) -> IO (IO b) join :: IO (IO b) -> IO b
мы можем объединить их следующим образом:
join . atomically :: STM (IO b) -> IO b
чтобы выполнить транзакцию STM и возвращённое ею действие IO.
msum :: (Foldable t, MonadPlus m) => t (m a) -> m a Исходный код
Сумма набора действий с использованием (<|>), обобщающая concat.
msum работает так же, как asum, но специализирована для MonadPlus.
Примеры
Базовое использование с экземпляром MonadPlus для Maybe:
>>> msum [Just "Hello", Nothing, Just "World"] Just "Hello"
mfilter :: MonadPlus m => (a -> Bool) -> m a -> m a Исходный код
Прямой эквивалент MonadPlus для filter.
Примеры
Функция filter — это просто mfilter, специализированная для монады списков:
filter = ( mfilter :: (a -> Bool) -> [a] -> [a] )
Пример использования mfilter с монадой Maybe:
>>> mfilter odd (Just 1) Just 1 >>> mfilter odd (Just 2) Nothing
filterM :: Applicative m => (a -> m Bool) -> [a] -> m [a] Исходный код
Это обобщение функции filter, основанной на списках.
runIdentity (filterM (Identity . p) xs) == filter p xs
Примеры
>>> filterM (\x -> do
putStrLn ("Keep: " ++ show x ++ "?")
answer <- getLine
pure (answer == "y"))
[1, 2, 3]
Keep: 1?
y
Keep: 2?
n
Keep: 3?
y
[1,3]
>>> filterM (\x -> do
putStr (show x)
x' <- readLn
pure (x == x'))
[1, 2, 3]
12
22
33
[2,3]
mapAndUnzipM :: Applicative m => (a -> m (b, c)) -> [a] -> m ([b], [c]) Исходный код
Функция mapAndUnzipM применяет свой первый аргумент к элементам списка и возвращает результат в виде пары списков. Эта функция в основном используется со сложными структурами данных или монадами состояния.
zipWithM :: Applicative m => (a -> b -> m c) -> [a] -> [b] -> m [c] Исходный код
Функция zipWithM обобщает zipWith для произвольных аппликативных функторов.
zipWithM_ :: Applicative m => (a -> b -> m c) -> [a] -> [b] -> m () Исходный код
zipWithM_ — это расширение zipWithM, которое игнорирует итоговый результат.
foldM :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b Исходный код
Функция foldM аналогична foldl, за исключением того, что её результат заключён в монаду. Обратите внимание, что foldM обрабатывает аргументы списка слева направо. Это может стать проблемой, если (>>) и «свёртываемая функция» не коммутативны.
foldM f a1 [x1, x2, ..., xm] == do a2 <- f a1 x1 a3 <- f a2 x2 ... f am xm
Если требуется вычисление справа налево, входной список следует развернуть.
Примечание: foldM — то же самое, что и foldlM
foldM_ :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m () Исходный код
Как foldM, но отбрасывает результат.
replicateM :: Applicative m => Int -> m a -> m [a] Исходный код
replicateM n act выполняет действие act n раз, а затем возвращает список результатов.
replicateM n (pure x) == replicate n x
Примеры
>>> replicateM 3 getLine hi heya hiya ["hi","heya","hiya"]
>>> import Control.Monad.State >>> runState (replicateM 3 $ state $ \s -> (s, s + 1)) 1 ([1,2,3],4)
replicateM_ :: Applicative m => Int -> m a -> m () Исходный код
Как replicateM, но отбрасывает результат.
Примеры
>>> replicateM_ 3 (putStr "a") aaa
Условное выполнение монадических выражений
guard :: Alternative f => Bool -> f () Исходный код
Условный отказ вычислений Alternative. Определяется так:
guard True = pure () guard False = empty
Примеры
Часто guard используют для условной передачи ошибки в монаде ошибок и условного отклонения текущего выбора в парсере на основе Alternative.
В качестве примера передачи ошибки в монаде ошибок Maybe рассмотрим безопасную функцию деления safeDiv x y, которая возвращает Nothing, если знаменатель y равен нулю, и Just (x `div`
y) в противном случае. Например:
>>> safeDiv 4 0 Nothing
>>> safeDiv 4 2 Just 2
Определение safeDiv с использованием охранных выражений, но без guard:
safeDiv :: Int -> Int -> Maybe Int
safeDiv x y | y /= 0 = Just (x `div` y)
| otherwise = Nothing
Определение safeDiv с использованием guard и Monad в записи do:
safeDiv :: Int -> Int -> Maybe Int safeDiv x y = do guard (y /= 0) return (x `div` y)
when :: Applicative f => Bool -> f () -> f () Исходный код
Условное выполнение выражений Applicative. Например,
Примеры
when debug (putStrLn "Debugging")
выведет строку Debugging, если булево значение debug равно True, и ничего не сделает в противном случае.
>>> putStr "pi:" >> when False (print 3.14159) pi:
unless :: Applicative f => Bool -> f () -> f () Исходный код
Противоположность when.
Примеры
>>> do x <- getLine
unless (x == "hi") (putStrLn "hi!")
comingupwithexamplesisdifficult
hi!
>>> unless (pi > exp 1) Nothing Just ()
Операторы монадического подъёма
liftM :: Monad m => (a1 -> r) -> m a1 -> m r Исходный код
Поднимает функцию в монаду. Эквивалентно fmap, но специализировано для монад.
liftM2 :: Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r Исходный код
Поднимает функцию в монаду, обрабатывая монадические аргументы слева направо.
Примеры
>>> liftM2 (+) [0,1] [0,2] [0,2,1,3]
>>> liftM2 (+) (Just 1) Nothing Nothing
>>> liftM2 (+) (+ 3) (* 2) 5 18
liftM3 :: Monad m => (a1 -> a2 -> a3 -> r) -> m a1 -> m a2 -> m a3 -> m r Исходный код
Поднимает функцию в монаду, обрабатывая монадические аргументы слева направо (ср. liftM2).
liftM4 :: Monad m => (a1 -> a2 -> a3 -> a4 -> r) -> m a1 -> m a2 -> m a3 -> m a4 -> m r Исходный код
Поднимает функцию в монаду, обрабатывая монадические аргументы слева направо (ср. liftM2).
liftM5 :: Monad m => (a1 -> a2 -> a3 -> a4 -> a5 -> r) -> m a1 -> m a2 -> m a3 -> m a4 -> m a5 -> m r Исходный код
Поднимает функцию в монаду, обрабатывая монадические аргументы слева направо (ср. liftM2).
ap :: Monad m => m (a -> b) -> m a -> m b Исходный код
Во многих случаях операции liftM можно заменить на ap, который поднимает применение функции.
return f `ap` x1 `ap` ... `ap` xn
эквивалентно
liftM<n> f x1 x2 ... xn
Примеры
>>> pure (\x y z -> x + y * z) `ap` Just 1 `ap` Just 5 `ap` Just 10 Just 51
Строгие монадические функции
(<$!>) :: Monad m => (a -> b) -> m a -> m b infixl 4 Исходный код
Строгая версия <$>.
Начиная с: base-4.8.0.0
© The University of Glasgow and others
Licensed under a BSD-style license (see top of the page).
https://downloads.haskell.org/~ghc/9.14.1/docs/libraries/base-4.22.0.0-66f8/Control-Monad.html