Quali problemi di programmazione risolvono Monads? [chiuso]


14

Ho letto molti post che spiegano cosa sono le monadi, come unite come bindfunzionano, alcune delle quali si immergono direttamente nella teoria delle categorie in modo così astratto (almeno per me) che fa sanguinare gli occhi, alcuni ignorandolo del tutto e toccando strane analogie di burritos, scatole e cosa no.

Dopo alcune settimane di studio e molti neuroni fritti, (penso) capisco come funzionano le Monadi. Ma c'è ancora una cosa che sfugge alla mia comprensione, qualcosa su cui pochi post toccano effettivamente (tranne IO e stato):

PERCHÉ?

Perché le monadi contano? Perchè sono così importanti? Quali sono i problemi che stanno risolvendo? Questi problemi possono essere risolti solo con Monadi o ci sono altri modi?


3
I programmi sono grandi e complessi. Abbiamo bisogno di modi per strutturarli. Ci sono molti modi. Le monadi sono una cosa sola. Le frecce sono una. I portatori sono uno. Oggetti, classi, funzioni, metodi, moduli, tratti, mixin, pacchetti, sono alcuni altri, Non è proprio chiaro quale sia la tua domanda specifica. Stai chiedendo perché dobbiamo strutturare i programmi?
Jörg W Mittag,

1
@ JörgWMittag: NON sto chiedendo perché dobbiamo strutturare i programmi. Ovviamente un grosso problema è diviso in quelli più piccoli che puoi risolvere e poi combinare per ottenere la soluzione per quello grande. Sto chiedendo quali problemi risolvono le Monadi. È così? Codice di strutturazione? È tutto questo clamore? Ad esempio, in Haskell è così che si esegue l'I / O. Lì, la monade è un'opera teatrale che finge di agire come qualcosa di puro quando in realtà non lo è. La mia domanda è nel titolo, non so come affermarlo in modo più chiaro.
Dummy Me,



1
@RobertHarvey: ho anche trovato i primi due link che hai aggiunto, ma come nelle risposte di questi e altri post, le risposte vanno direttamente a Forse, monadi di stato e IO, saltando rapidamente agli esempi o al codice e finendo con "c'è molto di problemi che possono essere risolti usando Monads ". Quali sono gli altri tipi di problemi? Sto cercando una risposta di livello superiore che invece di ripetere gli stessi esempi in realtà va alla radice dei problemi (qualunque essi siano) e spiegare come Monad li risolva e perché è la scelta migliore, invece di usare qualcos'altro. Grazie mille per il feedback però.
Dummy Me,

Risposte:


10

Non hai bisogno di monadi per risolvere nulla. Rendono semplicemente alcune cose più semplici. Molte persone diventano troppo astratte e teoriche quando spiegano le monadi. Per lo più, le monadi sono un modello che emerge ripetutamente nella programmazione. Riconoscendo tale modello, possiamo semplificare il nostro codice ed evitare di reimplementare determinate funzioni.

Per Haskell, da un punto di vista concreto, la cosa più visibile abilitata dalle monadi è la notazione . Le comprensioni di elenchi in Haskell e in altre lingue sfruttano anche pesantemente le monadi. Puoi anche creare librerie come Control.Monad .

Tutti forniscono utili semplificazioni e, una volta implementata per una monade, la ottieni automaticamente per tutte le monadi. Questo è uno dei motivi principali per cui il riutilizzo del codice è molto più semplice per la programmazione funzionale rispetto ad altri paradigmi.


2
In realtà direi che la cosa più visibile abilitata dalle monadi haskell è un modo semplice per avere effetti IO che funzionano davvero come previsto. Penso che chiunque si chieda cosa ci danno le monadi dovrebbe provare Miranda . Miranda è la lingua che Haskell è stata progettata per sostituire e dovrebbe essere molto facile da imparare per chiunque abbia esperienza Haskell. La differenza principale è che non ha IO monadico, il che rende il linguaggio molto più difficile da lavorare rispetto a Haskell per qualsiasi progetto non banale.
Jules,

Sì, IOè la monade più importante di Haskell , ma non stavo elencando esempi di singole monadi. Stavo elencando esempi delle astrazioni generali che abilitano. Stavo cercando di capire perché, ad esempio, il primo ragazzo a pensare di usare una monade per IO pensasse che fosse una buona idea in generale.
Karl Bielefeldt,

1
@Jules: Oppure guarda la storia di Haskell. Prima di Monad, i progettisti di Haskell avevano sperimentato Lazy Streams e Continuations come base per l'I / O, ed entrambi erano difficili da usare.
Jörg W Mittag,

5

È più facile capire se guardi le monadi particolari e vedi quali problemi risolvono. Ad esempio, in Haskell:

  • IO: consente all'IO di essere rappresentato nel sistema di tipi, in modo da poter chiaramente separare le funzioni pure dalle funzioni che eseguono l'IO.

  • Elenco: consente di eseguire la comprensione dell'elenco e calcoli nodeterministici.

  • Forse: una migliore alternativa ai null e supportare qualcosa di paragonabile all'operatore null-coalescente di C #.

  • Parsec: un comodo DSL per scrivere parser.

Quindi è facile (spero) vedere la logica delle singole monadi, dal momento che sono tutte abbastanza utili. Ma i problemi che risolvono sono anche abbastanza diversi e, a prima vista, non sembrano avere molto in comune, tranne per il fatto che sono tutti collegati a una logica per le operazioni di concatenamento. Le monadi sono utili perché ti permettono di costruire una tale varietà di strumenti.

Gli esempi sopra potrebbero essere implementati senza monadi? Certamente potrebbero essere implementati in modo ad hoc, ma avere monadi incorporati nel linguaggio consente il supporto diretto della lingua come la donotazione che funziona con tutte le monadi.


2

Una cosa che lo confonde è che le funzioni "popolari" piacciono binde <*>sono orientate alla prassi. Ma per capire i concetti è più facile guardare prima altre funzioni. Vale anche la pena notare che le monadi si distinguono perché sono un po 'overhyped rispetto ad altri concetti collegati. Quindi inizierò con i funzione.

I Functor offrono una funzione (nella notazione di Haskell) fmap :: (Functor f) => (a -> b) -> f a -> f b. In altre parole, hai un contesto in fcui puoi sollevare una funzione. Come puoi immaginare, quasi tutto è un funzione. Elenchi, forse, entrambe le funzioni, I / O, tuple, parser ... Ognuno rappresenta un contesto in cui può apparire un valore. Quindi puoi scrivere funzioni estremamente versatili che funzionano in quasi ogni contesto usando fmapo la sua variante in linea <$>.

Quali altre cose vuoi fare con i contesti? Potresti voler combinare due contesti. Così si potrebbe desiderare di ottenere una generalizzazione zip :: [a] -> [b] -> [(a,b)]per esempio come questo: pair :: (Monoidal f) => f a -> f b -> f (a,b).

Ma poiché è ancora più utile nella pratica, le librerie Haskell invece offrono Applicative, che è una combinazione di Functore Monoidal, e anche di Unit, che aggiunge semplicemente che puoi effettivamente mettere i valori "dentro" il tuo contesto unit.

Puoi scrivere funzioni estremamente generiche semplicemente affermando queste tre cose sul contesto in cui stai lavorando.

Monadè solo un'altra cosa che puoi affermare in più. Quello che non ho menzionato prima è che hai già due modi per combinare due contesti: non solo puoi pair, ma puoi anche impilarli, ad esempio puoi avere un elenco di elenchi. Nel contesto I / O, un esempio potrebbe essere un'azione I / O in grado di leggere altre azioni I / O da un file, quindi si avrà un tipo FilePath -> IO (IO a). Come possiamo liberarci di quello stacking per ottenere una funzione eseguibile IO a? Ecco dove arriva Monads join, ci permette di combinare due contesti sovrapposti dello stesso tipo. Lo stesso vale per i parser, forse ecc. Ed bindè solo un modo più pratico da usarejoin

Quindi un contesto monadico deve offrire solo quattro cose e può essere utilizzato con quasi tutti i macchinari sviluppati per l'I / O, per i parser, per i guasti, ecc.


1

Monads ti consente di esprimere vari calcoli non puri e di semplificare il codice

  • calcolo stateful (ottieni / imposta stato tramite monade)
  • I / O (registrazione, UI, file o semplicemente produce / utilizza un elenco di X)
  • Inoltre, flusso di controllo "non lineare" (es. Eccezioni, forse, ecc.)

E, soprattutto, senza scendere a compromessi con i costrutti del linguaggio puro e tirandone fuori un linguaggio più pulito


2
Vero - ma questo è solo una parte di ciò per cui vengono usate le monadi. Elenca le comprensioni o Maybenon sono correlate a nulla di esterno.
JacquesB,

Sarebbe utile se i downvoter spiegassero perché l'hanno fatto. Non vedo nulla di sbagliato in questa risposta.
Jules,

@JacquesB sono, tuttavia, stateful.
Jules,

1
Anche i tipi di mondo, i tipi di unicità, i tipi lineari ti consentono di farlo.
Jörg W Mittag,

@Jules Liste come monade del non determinismo è stateful? Potresti chiarire qual è la tua definizione di "stateful"?
Jack,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.