Je tente d'implémenter des foncteurs en Javascript sans utiliser de types de conteneur ([]
/{}
). Par conséquent, j'utilise uniquement des fonctions pures d'ordre supérieur pour les construire:Les foncteurs ou les monades peuvent-ils être exprimés uniquement avec des fonctions d'ordre supérieur?
const option = x => f => isAssigned(x) ? option(f(x)) : none;
const none = option(null);
const isAssigned = x => x !== null && x !== undefined;
const inc = x => x + 1;
const sqr = x => x * x;
const head = xs => xs[0]
const log = x => (console.log(x), x);
option(head([4])) (inc) (sqr) (log); // 25
option(head([])) (inc) (sqr) (log); // not executed
option
prend une valeur et une fonction pure, soulève la fonction dans son contexte, l'applique à la valeur et renvoie la aboutir dans le même contexte. Je suppose que c'est un foncteur. Cependant, il ne suit pas le prototcol de foncteur en Javascript, que chaque foncteur doit posséder une fonction de carte sur son prototype.
option
peut apparemment être étendue à un type comme monade (au moins il se comporte comme dans mon exemple):
const option = x => f => isAssigned(x) ? option(f(x)) : none;
const option_ = x => f => isAssigned(x) ? flatten(option(f(x))) : none;
const none = option(null);
const of = x => option(x); // return
const flatten = F => { // it gets a bit ugly here
let y;
F(z => (y = z, z));
return y;
};
// auxiliary functions
const compn = (...fs) => x => fs.reduceRight((acc, f) => f(acc), x);
const getOrElse = x => F => {
let y;
F(z => (y = z, z));
return isAssigned(y) ? y : x;
};
const isAssigned = x => x !== null && x !== undefined;
const log = prefix => x => (console.log(prefix, x), x);
const head = xs => xs[0];
const head_ = xs => option(xs[0]);
const sqr = x => x * x;
// some data
const xs = [5],
ys = [];
// run
const w = option(xs) (head),
x = option(ys) (head),
y = option_(xs) (head_),
z = option_(ys) (head_);
log("square head of xs:") (compn(sqr, getOrElse(1)) (w)); // 25
log("square head of ys:") (compn(sqr, getOrElse(0)) (x)); // 0
log("square head_ of xs:") (compn(sqr, getOrElse(0)) (y)); // 25
log("square head_ of ys:") (compn(sqr, getOrElse(0)) (z)); // 0
fourni option
est en fait un foncteur ma question est: Est-il possible d'exprimer chaque foncteur/monade uniquement avec des fonctions (pures) d'ordre supérieur, où les résultats des calculs contextuels (ou effectifs) sont conservés dans la pile d'appels?
pourquoi voulez-vous faire cela? Si "haskell dans le navigateur" est votre objectif, il existe d'autres solutions – niceman
@ftor Voulez-vous dire quelque chose comme [Codage de l'église] (https://en.wikipedia.org/wiki/Church_encoding)? – phg
@phg la base théorique, merci. Donc c'est théoriquement possible. Je me demande encore s'il y a des problèmes pratiques pour les implémenter en Javascript. Jusqu'à présent 'option' n'a pas de type (proto). Comment puis-je associer des fonctions (comme 'of') avec la bonne monade? De plus, 'option' est seulement une union. Il n'y a pas de balises ni de moyens de refléter les types possibles adoptés par le syndicat. – ftor