Ответ 1
Насколько мне известно, нет веской причины. Обратите внимание, что ваш Monad
также должен быть экземпляром Applicative
, поэтому вы можете использовать <*
и *>
вместо этого в качестве инструментов последовательности.
Класс Monad
определяет метод >>
, который последовательно выполняет два монадических действия:
>> :: Monad m => m a -> m b -> m b
Оператор привязки >>=
имеет эквивалент с переворотом аргумента, =<<
; как и команды монадической функции ( "рыбы" ) >=>
и <=<
. Кажется, что нет <<
, хотя (через несколько минут Hoogling). Почему это?
Изменить: я знаю, что это неважно. Мне просто нравится, как некоторые строки кода выглядят с помощью указателей слева. x <- doSomething =<< doSomethingElse
просто выглядит лучше, при этом все стрелки идут одинаково, чем x <- doSomethingElse >>= doSomething
.
Насколько мне известно, нет веской причины. Обратите внимание, что ваш Monad
также должен быть экземпляром Applicative
, поэтому вы можете использовать <*
и *>
вместо этого в качестве инструментов последовательности.
Здесь альтернативный ответ, так как аналогичный вопрос был недавно задан и отмечен как дубликат. Оказывается, совсем не ясно, каким должно быть определение (<<)
! Хотя эта проблема упоминалась в комментариях к более раннему ответу, я не думаю, что она была полностью прояснена, что здесь есть существенная проблема.
Очевидно, две разумные возможности для определения:
(<<) :: Monad m => m a -> m b -> m a
p << q = do {x <- p; q; return x} -- definition #1
p << q = do {q; p} -- definition #2
По аналогии с аппликативными операторами (<*)
и (*>)
ясно, что оператор new (<<)
должен сохранять порядок побочных эффектов слева направо и иметь только эффект переключения, какое действие возвращает возвращаемое значение Таким образом, определение № 1, очевидно, является правильным. Это имеет желаемое свойство, что <<
и <*
будут синонимичны для (с хорошим поведением) монад, так же как >>
и *>
являются синонимами, так что никаких сюрпризов.
Конечно, по аналогии с =<<
и >>=
ясно, что переключение направления знаков больше, чем должно, приводит к переключению аргументов, поэтому определение № 2, очевидно, является правильным. Это имеет желаемое свойство, что конвейер монадических операций:
u >>= v >>= w >> x >>= y
можно поменять местами с помощью операторов:
y =<< x << w =<< v =<< u
Это также сохраняет тождества для операторов Клейсли:
(f >=> g) x === f x >>= g
(f <=< g) x === f =<< g x
которые, конечно, выглядят так, как будто они должны держать.
Во всяком случае, я не знаю, если это было первоначальная причина (<<)
была опущена. (Вероятно, нет, так как это решение предшествовало бы введению аппликативных операторов, поэтому люди приняли бы "определение № 2" как единственную возможность), но я почти уверен, что сейчас это станет камнем преткновения, поскольку другое поведение of (<<)
и (<*)
были бы довольно неожиданными, учитывая тесную связь, которую люди ожидают между аппликативными и монадными операциями.