Do нотация используется для записи выражений общего вида
ex :: Monad m => m t
let ex = do
{ x <- foo -- foo :: Monad m => m a, x :: a
; y <- bar x -- bar x :: Monad m => m b, y :: b
; z <- baz x y -- baz x y :: Monad m => m c, z :: c
; quux x y z -- quux x y z :: Monad m => m t
}
Обратите внимание, что все m
одинаковы, а a
, b
, c
, ... могут отличаться, хотя t
в последнем типе подвыражения do и общий тип выражения do одинаковы.
Переменные do называются "связанными" с помощью конструкции <-
.Они входят в область действия при введении (слева от <-
) и остаются в области действия для всех последующих подвыражений do .
Одно встроенное монадическое выражение, доступное для любогомонада return :: Monad m => a -> m a
.Таким образом, x <- return v
связывает x
с v
, так что x
будет доступно в последующих подвыражениях и будет иметь значение v
.
Все переменные do ограничены этим do
блоком, и не может использоваться вне его.Область действия каждой переменной - это весь код в одном и том же блоке do
ниже / после привязки переменной.
Это также означает, что <-
является нерекурсивным связыванием, поскольку переменная не может идти как с правой, так и с левой стороны: это будет два разных в этом случае переменные с одинаковыми именами и переменная справа должны быть установлены где-то выше этой точки.
Здесь есть несколько общих закономерностей:
do { _ <- p ; _ <- q ; r } === do { p ; q ; r }
do { x <- p ; return x } === do { p } === p
do { x <- return v ; foo x } === do { foo v } === foo v
do { p ; q ; r } === do { p ; do { q ; r } }
=== do { do { p ; q } ; r }
do { x <- p ; === do { x <- p ;
y <- q x ; z <- do { y <- q x ;
return (foo x y) } return (foo x y) } ;
return z }
* * * * * * * * * * * * * * * Все выражения Monad m => m a
, в частности, выражения и, в частности, могут быть if - then - else
выражениями, причем как последовательные, так и альтернативные ветви имеют одинаковый монадический тип (что часто вводит в заблуждение начинающих):
do { x <- p ;
y <- if (pred x) then (foo x) else (bar x) ;
return (baz x y) }
обновление: Одним из главных моментов монады является ее полное отделение эффектов от чистых вычислений.Однажды в монаде вы не можете "выйти" .Монадические вычисления могут использовать чистые вычисления, но не наоборот.