Critica della monade IO che viene vista come una monade statale che opera sul mondo


46

La IOmonade di Haskell è spesso spiegata come una monade di stato in cui lo stato è il mondo. Quindi un valore di tipo IO amonade è visto come qualcosa di simile worldState -> (a, worldState).

Qualche tempo fa ho letto un articolo (o un blog / post di una mailing list) che ha criticato questo punto di vista e ha fornito diversi motivi per cui non è corretto. Ma non ricordo né l'articolo né i motivi. Qualcuno lo sa?

Modifica: l'articolo sembra perso, quindi iniziamo a raccogliere vari argomenti qui. Sto iniziando una taglia per rendere le cose più interessanti.

Modifica: L'articolo che stavo cercando è Affrontare la squadra imbarazzante: input / output monadici, concorrenza, eccezioni e chiamate in lingua straniera in Haskell di Simon Peyton Jones. (Grazie alla risposta di TacTics.)



@JoachimSauer Grazie, è anche un articolo interessante, ma non è quello che sto cercando. Quello era focalizzato sul paradigma dello stato del mondo.
Petr Pudlák,

In cima alla mia testa, i commenti qui sono un buon inizio
Adam,

1
Cosa significa "mondo" in questo contesto? Presumo che non significhi "La Terra". È una specie di portata globale? L'autore che ha scritto questo si sta vendendo a corto. Se vuole confondere e schiacciare contemporaneamente l'ego dei suoi lettori, dovrebbe chiamarlo "Lo stato è l'universo" o "Lo stato divino". Mondo. Pah! In questi giorni, voi giovani non aspirate abbastanza in alto!
GlenPeterson,

Risposte:


33

Il problema IO a = worldState -> (a, worldState)è che se ciò fosse vero, potremmo provarlo forever (putStrLn "Hello") :: IO ae undefined :: IO aessere uguali. Ecco la dimostrazione per gentile concessione di dolio (2010, irc):

forever m
 =
m >> forever m
 =
fix (\r -> m >> r)
 = {definition of >> for worldState -> (a, worldState)}
fix (\r -> \w -> r (snd $ m w))

Lemma: (\r w -> r (snd $ m w)) ⊥ = ⊥

(\r w -> r (snd $ m w)) ⊥
  =
\w -> ⊥ (snd $ m w))
  =
⊥ . snd . m
  =
⊥

Perciò forever m = fix (\r -> \w -> r (snd $ m w)) = ⊥

In particolare forever (putStrLn "Hello") = ⊥e quindi forever (putStrLn "Hello")e undefinedsono programmi equivalenti. Tuttavia, chiaramente non dovrebbero essere considerati programmi equivalenti, in teoria o in pratica.

Si noti che questo modello è sbagliato anche senza invocare la concorrenza.


7
Qualcuno è sorpreso che un programma non terminante sia equivalente alla undefinedpura semantica di Haskell? Si suppone che diversi inds siano indistinguibili nella semantica pura di Haskell! Ma quando pensiamo operativamente ai nostri programmi vogliamo distinguere anche diversi tipi di ⊥, anche quando IOnon sono coinvolti; Mi importa se il mio programma sta generando un'eccezione o sta entrando in un ciclo infinito, anche se puoi provare che sono uguali dimostrando che sono entrambi ⊥. Non è in realtà una contraddizione però.
Ben

3
Le denotazioni di ⊥ e [0,1 ..] sono distinte anche se sono entrambe "non terminanti". La differenza è che ⊥ indica calcoli non terminanti e non produttivi, mentre [0,1 ..] non è terminante ma produttivo. Ci aspettiamo (per sempre (putStrLn "Hello")) di avere una denotazione simile non terminante ma produttiva.
Russell O'Connor,

1
Ma forever (putStrLn "Hello")non è come [0,1..], sicuramente. La tua prova non è particolare worldState, quindi si applica anche alla monade statale normale. Quindi forever (someModificationWith "Hello")è anche denotazionalmente equivalente a ⊥. Non sono completamente sorpreso da quel risultato; non è produttivo nella semantica denotazionale e ciò che il computer sta facendo operativamente mentre aspettiamo per sempre è irrilevante. Stessa cosa per forever (putStrLn "Hello"); non produce e non dovrebbe produrre un nuovo stato mondiale che possiamo in qualche modo consumare pigramente.
Ben

I linguaggi di programmazione come Mercury e Clean che usano il passaggio esplicito dello stato mondiale per fornire un modello dichiarativo di IO sono fondamentalmente sbagliati?
Ben

@Ben ti riferisci a come funziona il passaggio del mondo con la concorrenza? Hai visto il codice rosetta per la concorrenza di Mercury? Mi chiedevo cosa significhi anche semanticamente.
CMCDragonkai,

12

Ecco una risposta banale: qualsiasi cambiamento allo stato della monade di stato è dovuto a qualsiasi azione eseguita nella monade. Se davvero la spiegazione "WorldState -> (a, WorldState)" rivendica la stessa proprietà, con WorldState è un valore puro che cambia solo la monade IO, è sbagliato. Il tempo cambia, il contenuto dei file, lo stato degli handle, ecc. Possono cambiare indipendentemente da ciò che accade nella monade IO. Questo è il punto della monade IO. Il fatto che GHC passi attorno a un valore RealWorld (o che fosse) al di sotto è di garantire che le cose vengano eseguite in ordine, per quanto ne so, se ciò (potrebbe essere solo qualcosa da mettere nel valore ST).


8
non è in realtà un problema. puoi modellare l'operazione di bind come eseguire una modifica allo stato mondiale derivata da un archivio di regole fisso ma inconoscibile.
sclv,

1
@sclv: sì, ma questo archivio di regole fisso ma inconoscibile è il fattore di differenziazione che rende l'IO non la monade dello stato, questa incoerenza non si trova nella monade dello stato
Jimmy Hoffa

Un argomento che ho sentito contro lo stato del WorldState è correlato alla concorrenza, sebbene non riesca a ricordare l'argomento esatto. Ma ancora, ipotizzo che anche WorldState possa codificare il futuro, quindi ancora non vedo davvero il problema. Certo, suppongo che mi manchi qualcosa.
Thomas Eding,

@JimmyHoffa: Puoi portare in giro il negozio di regole nello stato però.
sclv,

1
@JimmyHoffa: questo è lo scopo dell'astrazione. Inoltre, per dare seguito al mio commento iniziale, Clean modella IO come passaggio del mondo in modo esplicito e felice, usando tipi di unicità per assicurarsi di non imbrogliare e "duplicare" il mondo. Questo è un modo per far rispettare l'astrazione.
sclv,

12

Ho scritto un post sul blog su come modellare l'IO come una forma di coroutine asimmetrica che comunica con il sistema di runtime per la tua lingua. (È certamente la terza parte di una serie)

http://comonad.com/reader/2011/free-monads-for-less-3/

Quel post copre un po 'il motivo per cui è imbarazzante ragionare sulla semantica del "passaggio del mondo".


+1 - particolarmente interessante, poiché ho da tempo pianificato di implementare l'IO della lingua che sto progettando in modo simile a questo! :)
Jules il

8

Vedi Affrontare la squadra scomoda .

Il motivo principale è che i modelli di stato RealWorld della monade IO non funzionano bene con la concorrenza. SPJ in questo classico leggibile favorisce l'uso di una semantica operativa per capirlo.


Credo che questo sia l'articolo originale che stavo cercando, principalmente la sezione 3.1. Se l'avessi pubblicato prima che avessi modificato la domanda, avrei accettato la tua risposta, ma ora penso che sarà più giusto aspettare fino alla fine, per vedere tutte le idee che altri pubblicheranno.
Petr Pudlák,

5

La lamentela principale sui modelli statali di RealWorld è che, come afferma TacTics, il passaggio del mondo non funziona necessariamente con la concorrenza. Ma Wouter Swierstra e Thorsten Altenkirch hanno mostrato come ragionare sulla concorrenza come effetto "di passaggio del mondo", con una sequenza fissa ma arbitraria di fili interlacciati nel loro articolo "Beauty in the Beast: A Functional Sematics for the Awkward Squad": http : //www.staff.science.uu.nl/~swier004/Publications/BeautyInTheBeast.pdf

Il codice corrispondente a questo è su Hackage come IOSpec: http://hackage.haskell.org/package/IOSpec

Penso che la tesi di Wouter approfondisca: http://www.staff.science.uu.nl/~swier004/Publications/Thesis.pdf

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.