Quali problemi di programmazione risolvono le Monadi? [chiuso]

14

Ho letto molti post che spiegano cosa sono le monadi, come unit e bind funzionano, alcuni di loro si tuffano direttamente nella teoria delle categorie in modo 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 funziona Monads. Ma c'è ancora una cosa che sfugge alla mia comprensione, qualcosa a cui pochi messaggi in realtà toccano (tranne IO e stato):

PERCHE '?

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

    
posta Dummy Me 28.02.2016 - 15:44
fonte

4 risposte

10

Non hai bisogno di monadi per risolvere qualsiasi cosa. Semplicemente rendono le cose più semplici. Molte persone diventano troppo astratte e teoriche quando spiegano le monadi. Per lo più, le monadi sono uno schema che si ripete continuamente nella programmazione. Riconoscendo quel modello, possiamo semplificare il nostro codice ed evitare di reimplementare determinate funzioni.

Per Haskell, da un punto di vista concreto, la cosa più visibile che le monadi attivano è notazione notazione . Comprensione delle liste in Haskell e in altre lingue sfruttano anche le monadi. Puoi anche creare librerie come Control.Monad .

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

    
risposta data 28.02.2016 - 19:18
fonte
5

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

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

  • Elenco: ti permette di fare le liste di comprensione e nodeterministico calcoli.

  • Forse: un'alternativa migliore ai null e supporto di qualcosa paragonabile all'operatore a coalescenza nulla di C #.

  • Parsec: un comodo DSL per scrivere parser.

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

Gli esempi precedenti potrebbero essere implementati senza monadi? Certamente potrebbero essere implementati in modo ad-hoc, ma avere monadi incorporate nel linguaggio consente il supporto diretto di langauge come do -notation che funziona con tutte le monadi.

    
risposta data 29.02.2016 - 08:22
fonte
2

Una cosa che rende confusionaria è che le funzioni "popolari" come bind e <*> sono orientate alla praxis. Ma per capire i concetti è più facile guardare prima ad altre funzioni. Vale anche la pena notare che le monadi si distinguono perché sono un po 'overhyped rispetto ad altri concetti connessi. Quindi inizierò con i funtori invece.

I Functional offrono una funzione (in notazione Haskell) fmap :: (Functor f) => (a -> b) -> f a -> f b . In altre parole, hai un contesto f in cui puoi sollevare una funzione. Come puoi immaginare, quasi tutto è un funtore. Elenchi, Forse, O, funzioni, I / O, tuple, parser ... Ciascuno rappresenta un contesto in cui può apparire un valore. Quindi puoi scrivere funzioni estremamente versatili che funzionano in quasi tutti i contesti usando fmap o la sua variante in linea <$> .

Quali altre cose vuoi fare con i contesti? Potresti voler combinare due contesti. Quindi potresti voler ottenere una generalizzazione di zip :: [a] -> [b] -> [(a,b)] ad esempio in questo modo: pair :: (Monoidal f) => f a -> f b -> f (a,b) .

Ma poiché è ancora più utile in pratica, le librerie Haskell offrono invece Applicative , che è una combinazione di Functor e Monoidal , e anche di Unit , che aggiunge solo che puoi effettivamente inserire valori "dentro" il tuo contesto con unit .

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

Monad è solo un'altra cosa che puoi aggiungere. Ciò che non ho menzionato prima è che hai già due modi per combinare due contesti: puoi non solo pair , ma puoi anche raggrupparli, ad es. puoi avere una lista di liste. Nel contesto I / O, un esempio potrebbe essere un'azione di I / O in grado di leggere altre azioni I / O da un file, quindi si dovrebbe avere un tipo FilePath -> IO (IO a) . Come possiamo sbarazzarci di quell'impilamento per ottenere una funzione eseguibile IO a ? Ecco dove arriva Monad s join , ci consente di combinare due contesti impilati dello stesso tipo. Lo stesso vale per i parser, forse ecc. E bind è solo un modo più pratico di usare join

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

    
risposta data 28.02.2016 - 22:12
fonte
1

Monade consente di esprimere vari calcoli non puri e di semplificare il codice

  • computazione stateful (stato get / set tramite monad)
  • I / O (registrazione, interfaccia utente, file o solo produrre / consumare un elenco di X)
  • Inoltre, flusso di controllo "non lineare" (ad esempio, eccezioni, forse, ecc.)

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

    
risposta data 28.02.2016 - 19:54
fonte

Leggi altre domande sui tag