Как я узнал о монадах после чтения десятков уроков Я пытаюсь реализовать шаблон в JavaScript. Я использую LiveScript и Prelude, чтобы перевести некоторые примеры монахов Хаскелла.Monad pattern on receiver
Итак, монада, которую я пытаюсь реализовать в качестве упражнения, является монадой списка. Я писал, в LiveScript:
List = do ->
# unit :: a -> ma
unit = (a) -> [a]
# bind :: ma -> (a -> mb) -> mb
bind = (ma, f) --> concat (map f) ma
# lift :: (a -> b) -> ma -> mb
lift = (f, ma) --> bind ma, (a) -> unit f a
{unit, bind, lift}
add1 = (x) -> x+1
let {unit, bind} = List
x <- bind [1]
y <- bind [2]
z <- bind [3]
unit add1 x+y+z #=> [7]
(List.lift add1) [1 2 3] #=> [2 3 4]
Синтаксис LiveScript к функциям гнезда на тот же уровень отступа очень удобно, но это приводит к обратному вызову ад JavaScript, очевидно:
List = function(){
var unit, bind, lift;
unit = function(a){
return [a];
};
bind = curry$(function(ma, f){
return concat(map(f)(ma));
});
lift = curry$(function(f, ma){
return bind(ma, function(a){
return unit(f(a));
});
});
return { unit: unit, bind: bind, lift: lift };
}();
add1 = function(x){
return x + 1;
};
(function(arg$){
var unit, bind;
unit = arg$.unit, bind = arg$.bind;
bind([1], function(x){
return bind([2], function(y){
return bind([3], function(z){
return unit(add1(x + y + z));
});
});
});
}.call(this, List));
List.lift(add1)([1, 2, 3]);
Я хочу, чтобы реализовать шаблон на приемнике, чтобы иметь возможность использовать его так:
List([1]).bind([2]).bind([3]).do(function(x,y,z){ x+y+z });
После просмотра this video где Крокфорд объясняет монады в J avaScript (code), я понимаю, что представленный им MONAD
представляет собой объект с методами, которые также могут быть реализованы с помощью прототипов. Метод unit
является конструктором, а bind
- это метод экземпляра, который выполняет функцию по значению с данными аргументами. Затем lift
добавляет новый метод прототипу, который запускает заданную функцию по монадическому значению.
Но, это настоящая монада или монадический узор like jQuery? Я сомневаюсь в этом конкретном объяснении монад, потому что нет последовательности вычислений, метод bind
запускает функцию сразу и возвращает новый экземпляр «монады», это не композиция, как в монаде, который я реализовал в LiveScript, который был основанный на примерах Haskell.
Так что мой вопрос:
- Является ли моя реализация монады правильно?
- Crockford's implementation от monad correct?
Я не уверен, что «Список ([1]). Bind ([2]). Bind ([3]). Do (function (x, y, z) {x + y + z}); 'должен делать. 'bind' обычно принимает функцию (которая создает список)? – Bergi
Я думаю, что это часть, которую я еще не совсем понимаю, - как заставить монаду работать на приемнике, но по-прежнему использовать функцию композиции. Как это должно было бы выглядеть с моим примером тогда? – elclanrs
У вас есть три экземпляра монады, так что это будет нелегко. Эти обратные вызовы LiveScript, так же, как и Haskells, представляют собой просто синтаксический сахар для * необходимого * лифтинга обратного вызова. Вам еще нужно написать «List ([1]). Bind ((x) -> List ([2]). Bind ((y) -> List ([3]). Bind ((z) -> List .unit (х + у + г)))) '. Разумеется, для этого вы могли бы реализовать некоторые функции сахара, в этом случае ['lift3'] (http://hackage.haskell.org/package/base-4.6.0.1/docs/Control-Monad.html#v:liftM3). – Bergi