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 IO
emulation 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).
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
Könnten Sie bitte das ** Update ** klären? – damluar
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