Я бы начал с написания вашей собственной монады на JavaScript. Монада списка - отличное место для начала; Я считаю это наиболее полезным. Просто определите функции, которые делают следующее:
- Создайте список из одного данного элемента (позвоните по этому
mreturn
).
- Создать пустой список (позвоните по этому
mzero
).
- Добавить один список в другой (позвоните по этому номеру
mplus
).
- Применение функции для преобразования каждого элемента в данном списке (вызовите это
map
).
- "Свести" список списков в простой список путем объединения списков (назовите это
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() } });