2016-04-13 12 views
1

Nach dem Eintauchen in Monaden verstehe ich, dass sie ein allgemeines Konzept sind, um Berechnungen innerhalb eines Kontexts (Versagen, Nicht-Determinismus, Zustand usw.) zu verketten und es gibt keine Magie dahinter.In welchem ​​Sinne ist IO Monade speziell (wenn überhaupt)?

Noch IO-Monade fühlt sich auch wenn nicht magisch, aber besonders.

  • Sie können nicht entkommen IO Monade wie können Sie mit anderen Monaden
  • IO Aktion kann nur durch die main Funktion
  • IO an der Unterseite ist immer einer Monade Transformatoren Kette
  • Implementierung von IO betrieben werden Monad ist unklar und Quellcode zeigt einige Haskell Interna

Was sind die Gründe für die oben genannten Punkte? Was macht IO so besonders?

Update: im reinen Code spielt die Reihenfolge der Auswertung keine Rolle. Aber es ist wichtig, wenn IO (wir wollen Kunden speichern, bevor wir es lesen). Von dem, was ich verstehe, gibt uns IO Monad solche Bestellgarantien. Ist es eine Eigenschaft einer Monade im Allgemeinen oder ist es etwas Spezifisches für IO Monade?

Antwort

2

Ähnliche Aussagen könnten über die ST Monade gemacht werden, oder wohl die STM Monade (obwohl Sie das tatsächlich auf IO implementieren können).

Im Grunde sind Dinge wie der Reader Monad, Error Monad, Writer Monad, etc., alle nur reiner Code. Die ST und IO Monaden sind die einzigen, die wirklich unreine Sachen machen (Zustandsveränderung, usw.), also sind sie in reinem Haskell nicht definierbar. Sie müssen irgendwo im Compiler "fest verdrahtet" sein.

7

Sie können nicht entkommen IO Monade wie können Sie mit anderen Monaden

Ich bin mir nicht sicher, was Sie “ Flucht ” bedeuten. Wenn Sie meinen, irgendwie die interne Darstellung der monadischen Werte (z. B. Liste -> Sequenz von Cons-Zellen) –, die ein Implementierungsdetail ist. In der Tat können Sie an IOemulation in pure Haskell – im Grunde nur eine State über eine Menge von global verfügbaren Daten definieren. Das hätte die ganze Semantik von IO, aber ohne tatsächlich mit der realen Welt zu interagieren, nur eine Simulation davon.

Wenn Sie meinen, können Sie “ Auszugswerte ” aus der Monade – Nö, das ist in der Regel nicht möglich, auch für die meisten reinen Haskell Monaden. Zum Beispiel können Sie nicht einen Wert von Maybe a extrahieren (könnte Nothing) oder Reader b a (was ist, wenn b ist unbewohnt?)

IO Aktion kann nur durch die main Funktion

Nun laufen in gewissem Sinne alles kann nur von der main Funktion ausgeführt werden.Code, der nicht in irgendeiner Weise von main aufgerufen wird, wird nur dort sitzen, Sie könnten es durch undefined ersetzen, ohne etwas zu ändern.

IO ist immer an der Unterseite eines monadisch Transformatoren Kette

stimmt, aber das ist auch der Fall bei z.B. ST.

Implementierung von IO Monade ist unklar und Quelltext zeigt einige Haskell

Interna

Nochmal: Implementierung ist nur, na ja, ein Implementierungsdetail. Die Komplexität von IO Implementierungen hat tatsächlich viel damit zu tun, dass es stark optimiert ist; das gleiche gilt auch für spezialisierte reine Monaden (z. B. attoparsec).

As I already said), sind viel einfachere Implementierungen möglich, sie wären einfach nicht so nützlich wie der vollwertige optimierte Real-World IO Typ.

Glücklicherweise muss die Implementierung Sie nicht wirklich stören; die innerhalb von IO kann unklar sein, aber die außerhalb, die tatsächliche monadische Schnittstelle, ist ziemlich einfach.

in reiner Code-Auswertung Reihenfolge keine Rolle spielt

Vor allem – Auswerteauftrag kann Materie in reinem Code!

Prelude> take 10 $ foldr (\h t -> h `seq` (h:t)) [] [0..] 
[0,1,2,3,4,5,6,7,8,9] 
Prelude> take 10 $ foldr (\h t -> t `seq` (h:t)) [] [0..] 
^CInterrupted. 

Aber in der Tat kann man nie falsch, nicht ⊥ Ergebnis aufgrund misordered reinen Code-Auswertung. Dies gilt jedoch nicht für die Neuanordnung von monadischen Aktionen (IO oder anders), da die Änderung der Reihenfolge der Reihenfolge die tatsächliche Struktur der resultierenden Aktion ändert, nicht nur die Evaluierungsreihenfolge, die die Laufzeit Konstrukt diese Struktur verwendet.

Zum Beispiel (Liste Monade):

Prelude> [1,2,3] >>= \e -> [10,20,30] >>= \z -> [e+z] 
[11,21,31,12,22,32,13,23,33] 
Prelude> [10,20,30] >>= \z -> [1,2,3] >>= \e -> [e+z] 
[11,12,13,21,22,23,31,32,33] 

Alles, was gesagt, sicherlich IO ganz Besonderes ist, in der Tat denke ich, einige Leute es eine Monade zu nennen zögern (es ein bisschen unklar ist, was es ist eigentlich soll für IO bedeuten, die Monadengesetze zu erfüllen). Insbesondere Lazy IO ist eine massive Unruhestifter (und am besten nur vermieden, zu jeder Zeit).

+0

Wenn ich escape oder run sage, meine ich run * -Funktionen, die uns erlauben, Status- oder Leseraktionen auszuführen. Ich denke, es gibt keine sichere Run-IO-Funktion. Es wäre nett zu verstehen, warum – damluar

+0

Könnten Sie bitte das ** Update ** klären? – damluar

+0

Diese 'run *' Funktionen tun nichts "ausführen". Sie packen die interne Repräsentation einfach aus. Im Fall von "IO" wird dies nicht offiziell exportiert (aber, wie ich zweimal sagte, es gibt alternative Implementierungen von "IO", die auf eine einfache Zustands-Monade herunterkochen). – leftaroundabout