Изучая Clojure, я целую вечность пытался понять монады - что это такое и как мы можем их использовать ... с не слишком большим успехом.Тем не менее, я нашел отличную серию «Монады для чайников» - http://vimeo.com/20717301 - Брайана Марика для Clojure
До сих пор мое понимание монад таково, что это своего рода макрос в этомон позволяет написать набор утверждений в форме, которая легко читается, но монады гораздо более формализованы.Мои наблюдения ограничиваются двумя примерами:
1.Монада идентификации (или монада let) взята из http://onclojure.com/2009/03/05/a-monad-tutorial-for-clojure-programmers-part-1/
Форма, которую мы хотим записать:
(let [a 1
b (inc a)]
(* a b))
и соответствующая монада
(domonad identity-m
[a 1
b (inc a)]
(* a b))
2.Монада последовательности (или монада for) взята из http://onclojure.com/2009/03/06/a-monad-tutorial-for-clojure-programmers-part-2/
Форма, которую мы хотим написать:
(for [a (range 5)
b (range a)]
(* a b))
и соответствующая монада
(domonad sequence-m
[a (range 5)
b (range a)]
(* a b))
Определения монад в Clojure
Просмотр источника с использованием библиотеки монад clojure - https://github.com/clojure/algo.monads:
user=>(use 'clojure.algo.monads)
nil
Монада идентификации:
user=> (source identity-m)
(defmonad identity-m
[m-result identity
m-bind (fn m-result-id [mv f]
(f mv))
])
последовательность монада:
user=> (source sequence-m)
(defmonad sequence-m
[m-result (fn m-result-sequence [v]
(list v))
m-bind (fn m-bind-sequence [mv f]
(flatten* (map f mv)))
m-zero (list)
m-plus (fn m-plus-sequence [& mvs]
(flatten* mvs))
])
Итак, мой вывод заключается в том, что монада является своего рода обобщенной функцией высшего порядка, которая принимает входную функцию и входные значения, добавляет свои собственныеуправляет логикой и выдает «вещь», которую можно использовать в блоке «домонад».
Вопрос 1
Итак, наконец, к вопросам: я хочунаучитесь писать монаду и скажите, что я хочу написать «монаду карты», которая имитирует форму «карты» в clojure:
(domonad map-m
[a [1 2 3 4 5]
b [5 6 7 8 9]]
(+ a b))
должен быть эквивалентен
(map + [1 2 3 4 5] [5 6 7 8 9])
ивернуть значения
[6 8 10 12 14]
Если я посмотрю на источник, он должен дать мне что-то похожее на identity-m и sequence-m:
user=> (source map-m)
(defmonad map-m
[m-result ...
m-bind ...
m-zero ...
m-plus ...
])
Вопрос 2
Я также хочу иметь возможность определить «redu-m» так, чтобы я мог написать:
(domonad reduce-m
[a [1 2 3 4 5]]
(* a))
это может потенциальнодай мне 1 x 2 x 3 x 4 x 5 = 120 или
(domonad reduce-m
[a [1 2 3 4 5]
b [1 2 3 4 5]]
(+ a b))
даст мне (1 + 2 + 3 + 4 + 5) + (1 + 2 + 3 + 4 + 5) =30
Наконец Могу ли я также написать «монаду juxt», которая имитирует функцию juxt, но вместо передачи значений для привязки я передаю набор функций.:
(domonad juxt-m
[a #(+ % 1)
b #(* % 2)]
'([1 2 3 4 5] b a) )
дает
[ [2 2] [4 3] [6 4] [8 5] [9 6] ]
Потенциально, я мог бы делать все эти вещи с помощью макросов, поэтому я не знаю, насколько полезными будут эти «монады» или онидаже рассматривал «монады» ... Имея все ресурсы в интернете, мне кажется, что если я хочу изучать монады должным образом, я должен выучить Хаскель, и сейчас изучать другую синтаксическую форму слишком сложно.Я думаю, что нашел некоторые ссылки, которые могут быть актуальны, но это слишком загадочно для меня
Пожалуйста, может кто-нибудь пролить свет!