Монады в JavaScript? - PullRequest
       21

Монады в JavaScript?

11 голосов
/ 28 декабря 2011

Как будет выглядеть пример кода JavaScript, который использует Monad?Я спрашиваю, потому что понимание Monad гораздо яснее, если я смогу увидеть пример кода (а JavaScript - простой, функциональный язык, он мог бы быть лучшим языком для изучения).

1 Ответ

18 голосов
/ 28 декабря 2011

Я бы начал с написания вашей собственной монады на JavaScript. Монада списка - отличное место для начала; Я считаю это наиболее полезным. Просто определите функции, которые делают следующее:

  1. Создайте список из одного данного элемента (позвоните по этому mreturn).
  2. Создать пустой список (позвоните по этому mzero).
  3. Добавить один список в другой (позвоните по этому номеру mplus).
  4. Применение функции для преобразования каждого элемента в данном списке (вызовите это map).
  5. "Свести" список списков в простой список путем объединения списков (назовите это join).

Это определяет то, что известно как «аддитивная монада» (mzero и mplus образуют «аддитивную» часть). Поиграйте, чтобы узнать, что интересного вы можете сделать , используя только эти функции для работы со списками. Например, вы можете вычислить список всех четных чисел в таблице умножения школьника следующим образом:

var nums = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
var even_products = join(map(join(map(nums, function (x) {
        return map(nums, function(y) { return x * y })
    })),
    function (x) { if (x % 2 == 0) { return mreturn(x) } else { return mzero() } }
));

В качестве альтернативы объедините map и join вместе в одну функцию, определенную как function bind(l, f) { return join(map(l, f)) }. bind может использоваться вместо map и join и используется чаще, например, Haskell. Затем можно написать то же самое упражнение выше:

var nums = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
var even_products = bind(
    bind(nums, function (x) {
        return bind(nums, function (y) { return mreturn(x * y) })
    }),
    function (x) { if (x % 2 == 0) { return mreturn(x) } else { return mzero() } }
);

Наконец, вы можете захотеть включить эти функции как часть нового прототипа списка (или того, что JavaScript имеет для классов сегодня), так что вы можете вместо этого написать jQuery-esque:

var nums = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ];
var even_products = nums
    .bind(function (x) { return nums.bind(function (y) { return mreturn(x * y) }) })
    .bind(function (x) { if (x % 2 == 0) { return mreturn(x) } else { return mzero() } });
...