Can a monad be thought of as a function that accepts a value and wraps it such that it meets specific interface and behavioral constraints that have been found to be useful when working in a functional style?
No. La funzione che racchiude un valore è un'unità.
Se stai cercando di capire se ha senso spiegare le monadi come una funzione unitaria che restituisce un oggetto con un metodo di bind che segue le leggi monad, non funziona del tutto. Il problema è che ci sono valori monadici che non possono essere creati con la funzione dell'unità.
Ad esempio, nella monade Maybe, il valore Nothing non può essere creato con l'unità e l'intero punto dell'esistenza della monade Maybe è di consentire il valore Nothing.
In generale, i valori monadici creati dalla funzione di unità sono semplici, noiosi e chiari, e non illustrano il motivo per cui volevamo avere la monade con cui abbiamo a che fare in primo luogo. L'unità è ideale per trasformare valori semplici in valori monadici e funzioni semplici in funzioni monadiche per la compatibilità, ma il gioco è fatto.
Dopo averci pensato un po ', sono stato in grado di elaborare una prova su carta che tutte le monadi utili hanno valori monadici che non possono essere creati dall'unità. (Specificamente, o c'è solo un valore monadico nella monade (che è inutile), o la monade è isomorfa alla monade dell'identità (che è inutile nello stesso modo in cui la funzione di identità è inutile), o la monade ha valori monadici che non può essere creato dall'unità.)
Questo è sbagliato
Monad(x).bind(function(x){return x;}) == Monad(x); // for all x
dovrebbe essere
unit(x) == function(x){return Monad(x);} // I'm assuming this is what you mean by Monad(x)
Mx.bind(unit) == Mx; // for all monadic values Mx
Questo
Monad(x).bind(fn) == Monad(fn(x)); // for all x, fn
dovrebbe essere
Monad(x).bind(fn) == fn(x); // for all values x and monadic functions fn
È possibile eseguire il binding con qualsiasi funzione monadica, che è una funzione di un argomento che restituisce un valore monadico dello stesso tipo su cui si basa l'implementazione di bind, ma non è possibile associare tutte le funzioni.
Questo è sbagliato
Monad(x).bind(fn1).bind(fn2) == Monad(x).bind(function(x) {
return fn2(fn1(x));
});
dovrebbe essere questo
// for any monadic value Mx and any 2 monadic functions fn1 and fn2 whose types line up
Mx.bind(fn1).bind(fn2) == Mx.bind(function(x) {
return fn1(x).bind(fn2);
});
iii. It has a "bind" method that takes a monad, a function that takes a some type and returns a monad (is this another monad?), and returns a monad.
Stai usando la parola monad per indicare diverse cose, che penso sia soddisfacente, ma è potenzialmente poco chiaro per le persone che non hanno ancora messo le loro teste in giro per le monadi. Ci sono tre cose che potresti significare con la monade: il modello generale delle monadi / monadi in generale, una monade specifica o un valore monadico. Le Monade in generale sono ciò che stai cercando di definire / spiegare, una monade specifica sarebbe una particolare istanza di questo schema / interfaccia generale (come la monade Forse o la monade Lista), e un valore monadico è un valore del tipo che output unit o bind (come la lista [1,2,3]
per la lista monad).
Quindi possiamo semplificarlo a
iii. It has a "bind" method that takes a monadic value and a monadic function and returns a monadic value.
Sebbene ciò non chiarisca che il bind non funziona tra diverse monadi o che il tipo di output della funzione monadica è uguale al tipo di output del bind.
Un altro modo di guardare il legame è come un equivalente monadico dell'applicazione di funzione. L'applicazione di funzione normale assume un valore normale e una funzione semplice e restituisce un valore normale. Il legame monadico assume un valore monadico e una funzione monadica e restituisce un valore monadico. Se hai un valore monadico Mx
e una funzione monadica fn
, non puoi fare fn(Mx)
, perché fn
non funziona su valori monadici. Ma puoi fare Mx.bind(fn)
.
i. It has a type constructor that defines its type (What is this?).
Un costruttore di tipi è un concetto che esiste in Haskell, ma non in javascript. Non sono sicuro del modo migliore per parlare di questo in javascript, ma probabilmente finirei a parlare di Classi, perché anche se non esistono realmente in javascript, i programmatori javascript sanno qual è il concetto. Per qualsiasi monade, ci deve essere una definizione di cosa significa valore monadico per quella particolare monade, ed è quello che va qui.