Ответ 1
Ясно, что >>=
не является способом представления композиции функции. Состав функции просто выполняется с помощью .
. Тем не менее, я не думаю, что любая из статей, которые вы прочитали, означала это.
То, что они имели в виду, это "модернизация" композиции функций для работы непосредственно с "монадическими функциями", то есть с функциями формы a -> m b
. Техническим термином для таких функций являются стрелки Kleisli, и действительно они могут быть составлены с помощью <=<
или >=>
. (В качестве альтернативы вы можете использовать Category
экземпляр, тогда вы также можете составить их с помощью .
или >>>
.)
Однако разговоры о стрелках/категориях, как правило, путают особенно для новичков, так же как точечные определения обычных функций часто сбивают с толку. К счастью, Haskell позволяет нам выражать функции также в более привычном стиле, который фокусируется на результатах функций, а не на самих функциях, как на абстрактных морфизмах & dagger;. Это делается с абстракцией лямбда: вместо
q = h . g . f
вы можете написать
q = (\x -> (\y -> (\z -> h z) (g y)) (f x))
... Конечно, предпочтительным стилем будет (это всего лишь синтаксический сахар для абстракции лямбда!) & ddagger;
q x = let y = f x
z = g y
in h z
Обратите внимание, что в выражении лямбда в основном композиция была заменена приложением:
q = \x -> (\y -> (\z -> h z) $ g y) $ f x
Адаптировано к стрелкам Kleisli, это означает вместо
q = h <=< g <=< f
вы пишете
q = \x -> (\y -> (\z -> h z) =<< g y) =<< f x
который снова выглядит, конечно, намного приятнее с переворачиваемыми операторами или синтаксическим сахаром:
q x = do y <- f x
z <- g y
h z
Итак, =<<
соответствует <=<
, как $
соответствует .
. Причина, по которой все еще имеет смысл называть его композиционным оператором, состоит в том, что помимо "применения к значениям" оператор >>=
также выполняет нетривиальный бит о композиции стрелки Клейсли, для которой не нужна композиция функций: объединение монадических слоев.
& dagger; Причина этого в том, что Hask является декартовой замкнутой категорией, в особенно четко обозначенная категория. В такой категории стрелки могут, в широком смысле, быть определены совокупностью всех их результатов при применении к простым значениям аргументов.
& ddagger; @adamse отмечает, что let
не является синтаксическим сахаром для абстракции лямбда. Это особенно актуально в случае рекурсивных определений, которые вы не можете напрямую писать с помощью лямбда. Но в простых случаях, подобных этому, let
ведет себя как синтаксический сахар для лямбда, так же, как do
обозначение - синтаксический сахар для лямбда и >>=
. (Кстати, есть расширение, которое допускает рекурсию даже в нотации do
... оно обходит ограничение лямбда с помощью комбинаторов с фиксированной запятой.)