В ответ на ваш вопрос можно многое сказать, однако, поскольку вы задали этот вопрос, я предложу это «практическое правило».
Если вы используете do
-обозначение и ваши сгенерированные значения [1] не используются в выражениях, которые вы упорядочиваете [2], то этот код может преобразоваться в стиль Applicative. Аналогично, если вы используете одно или несколько сгенерированных значений в выражении, которое упорядочено, то вы должны использовать Monad
, а Applicative
недостаточно для достижения того же кода.
Например, давайте посмотрим на следующий код:
do a <- e1
b <- e2
c <- e3
return (f a b c)
Мы видим, что ни в одном из выражений справа от <-
не появляется ни одно из сгенерированных значений (a
, b
, c
). Поэтому мы можем преобразовать его в использование кода Applicative. Вот одно из возможных преобразований:
f <$> e1 <*> e2 <*> e3
и еще:
liftA3 f e1 e2 e3
С другой стороны, возьмите этот фрагмент кода, например:
do a <- e1
b <- e2 a
c <- e3
return (f b c)
Этот код не может использовать Applicative
[3], потому что сгенерированное значение a
будет использовано позже в выражении в понимании. Для получения результата нужно использовать Monad
- попытаться включить его в Applicative
, чтобы понять, почему.
Есть еще несколько интересных и полезных подробностей по этому вопросу, однако я просто хотел дать вам это практическое правило, с помощью которого вы можете просмотреть do
-понимание и довольно быстро определить, можно ли его учесть в * 1031. * код стиля.
[1] Те, которые появляются слева от <-
.
[2] Выражения, которые появляются справа от <-
.
[3] Строго говоря, его части могли бы, с учетом e2 a
.