Perché gli effetti collaterali sono modellati come monadi in Haskell?



Answers

Qualcuno potrebbe dare alcuni suggerimenti sul perché i calcoli impuri in Haskell sono modellati come monadi?

Questa domanda contiene un malinteso diffuso. Impurità e Monade sono nozioni indipendenti. L'impurità non è modellata da Monad. Piuttosto, ci sono alcuni tipi di dati, come IO , che rappresentano il calcolo imperativo. E per alcuni di questi tipi, una piccola parte della loro interfaccia corrisponde al modello di interfaccia chiamato "Monad". Inoltre, non vi è alcuna spiegazione pura / funzionale / denotativa conosciuta di IO (ed è improbabile che lo sia, considerando lo scopo "sin bin" di IO ), sebbene ci sia la storia comunemente raccontata di World -> (a, World) essere il significato di IO a . Quella storia non può descrivere in modo IO , perché IO supporta la concorrenza e il non-determinismo. La storia non funziona nemmeno quando si tratta di calcoli deterministici che consentono l'interazione mid-computation con il mondo.

Per ulteriori spiegazioni, vedere questa risposta .

Modifica : rileggendo la domanda, non penso che la mia risposta sia abbastanza precisa. I modelli di calcolo imperativo spesso si rivelano monadi, proprio come diceva la domanda. Il richiedente potrebbe non dare per scontato che la monade in qualche modo consenta la modellizzazione del calcolo imperativo.

Question

Qualcuno potrebbe dare alcuni suggerimenti sul perché i calcoli impuri in Haskell sono modellati come monadi?

Voglio dire Monad è solo un'interfaccia con 4 operazioni, quindi qual è stato il ragionamento per la modellazione di effetti collaterali in esso?




Sopra ci sono ottime risposte dettagliate con background teorico. Ma voglio dare la mia opinione su IO monade. Non sono un esperto programmatore di haskell, quindi potrebbe essere piuttosto ingenuo o addirittura sbagliato. Ma mi ha aiutato ad affrontare in qualche misura la monade dell'IO (nota che non si riferisce ad altre monadi).

Per prima cosa voglio dire, quell'esempio con "mondo reale" non è troppo chiaro per me in quanto non possiamo accedere ai suoi stati precedenti (nel mondo reale). Può essere che non si riferisca a calcoli monografici ma è desiderato nel senso della trasparenza referenziale, che è generalmente presente nel codice haskell.

Quindi vogliamo che il nostro linguaggio (haskell) sia puro. Ma abbiamo bisogno di operazioni di input / output, perché senza di loro il nostro programma non può essere utile. E quelle operazioni non possono essere pure per loro natura. Quindi l'unico modo per affrontarlo è separare le operazioni impure dal resto del codice.

Qui viene la monade. In realtà, non sono sicuro, che non possa esistere altro costrutto con proprietà simili simili, ma il punto è che monad ha queste proprietà, quindi può essere usato (ed è usato con successo). La proprietà principale è che non possiamo sfuggire a questo. L'interfaccia di Monad non ha operazioni per sbarazzarsi della monade attorno al nostro valore. Altre (non IO) monadi forniscono tali operazioni e consentono la corrispondenza del modello (ad esempio, forse), ma tali operazioni non sono nell'interfaccia di monad. Un'altra proprietà richiesta è la capacità di concatenare le operazioni.

Se pensiamo a ciò di cui abbiamo bisogno in termini di sistema di tipi, arriviamo al fatto che abbiamo bisogno di digitare con il costruttore, che può essere avvolto attorno a qualsiasi valore. Il costruttore deve essere privato, poiché ne vietiamo la fuga (ad esempio la corrispondenza del modello). Ma abbiamo bisogno di una funzione per mettere valore in questo costruttore (qui ritorna in mente). E abbiamo bisogno del modo di concatenare le operazioni. Se ci pensiamo per un po ', arriveremo al fatto che l'operazione di concatenazione deve avere tipo come >> = ha. Quindi, arriviamo a qualcosa di molto simile alla monade. Penso che, se analizziamo ora possibili situazioni contraddittorie con questo costrutto, arriveremo agli assiomi monad.

Nota che il costrutto sviluppato non ha nulla in comune con l'impurità. Ha solo proprietà, che noi desideriamo essere in grado di gestire operazioni impure, vale a dire senza sfuggire, concatenare e un modo per entrare.

Ora alcune serie di operazioni impure sono predefinite dalla lingua all'interno di questo monade IO selezionato. Possiamo combinare queste operazioni per creare nuove operazioni non pure. E tutte quelle operazioni dovranno avere IO nel loro tipo. Si noti tuttavia che la presenza di IO nel tipo di alcune funzioni non rende impura questa funzione. Ma come ho capito, è una cattiva idea scrivere funzioni pure con IO nel loro tipo, poiché inizialmente era nostra idea separare le funzioni pure e impure.

Infine, voglio dire, che la monade non trasforma le operazioni impure in puri. Permette solo di separarli in modo efficace. (Ripeto, che è solo la mia comprensione)




Qualcuno potrebbe dare alcuni suggerimenti sul perché i calcoli impuri in Haskell sono modellati come monadi?

Bene, perché Haskell è puro . È necessario un concetto matematico per distinguere tra calcoli non puri e puri a livello di tipo e per modellizzare i flussi di programma in rispettivamente.

Questo significa che dovrai finire con qualche tipo di I / IO a che modella un calcolo non puro. Quindi è necessario conoscere i modi per combinare questi calcoli di cui applicare in sequenza ( >>= ) e sollevare un valore ( return ) sono quelli più evidenti e di base.

Con questi due, hai già definito una monade (senza nemmeno pensarci);)

Inoltre, le monadi forniscono astrazioni molto generiche e potenti , quindi molti tipi di flusso di controllo possono essere convenientemente generalizzati in funzioni liftM come la sequence , il liftM o la sintassi speciale, rendendo l'unpureness non un caso così speciale.

Vedere le monadi nella programmazione funzionale e nella tipizzazione dell'unicità (l'unica alternativa che conosco) per maggiori informazioni.




In realtà è un modo abbastanza pulito per pensare all'I / O in modo funzionale.

Nella maggior parte dei linguaggi di programmazione, esegui operazioni di input / output. In Haskell, immagina di scrivere il codice per non eseguire le operazioni, ma per generare un elenco delle operazioni che vorresti fare.

Le Monade sono semplicemente sintassi per questo.

Se vuoi sapere perché le monadi sono opposte a qualcos'altro, credo che la risposta sia che sono il modo migliore per rappresentare l'I / O a cui la gente potrebbe pensare quando stavano facendo Haskell.




Links