Die elementarste Art von Ein- und Ausgabe in Gofer stellen die
Dialogfunktionen dar. Leider ist diese Art des I/O recht unhandlich
und konterintuitiv. I/O Funktionen werden als ein Dialog zwischen Programm
und Betriebssystem modelliert. [O'D85] Dieser Dialog stellt
sich dar als eine unendliche Liste von Anfragen an das Betriebssystem [Request] auf Seite des Programms als Kommunikationspartner und eine
ebensolche Liste von Antwortmeldungen auf diese Anfragen des
Betriebssystems [Response].
Wir haben also die zwei Listen:
als Teile unseres Kommunikationsprozesses, wobei jeweils die
Antwort des Betriebssystems auf die Meldung
des Programms sein
sollen.
Gofer-Funktionen, die Daten einlesen oder ausgeben, müssen vom Typ Dialogue sein. Dialogue ist durch folgendes Typ-Synonym definiert:
type dialogue = [Response] -> [Request]Eine Funktion dieses Typs erzeugt also eine Liste von Requests an das Betriebssystem und erhält von diesem die Antworten (Responses) als Eingabe. Mögliche Responses sind:
Success Str String Failure IOErrorwobei IOError eine der folgenden Formen annehmen kann:
WriteError String ReadError String SearchError String FormatError String OtherError StringMögliche Requests sind:
helloWorld :: Dialogue helloWorld resp = [AppendChan stdout "hello, World"] showFile :: String -> Dialogue showFile name ~(read:_) = [ReadFile name,AppendChan stdout result] where result = case read of Str contents -> contents Failure _ -> "Can't open " ++ name moin ~(~Success: ~(~(Str zahl) : ~(~Success:[]))) = [AppendChan stdout "Geben Sie ein Zahl ein: ", ReadChan stdin, AppendChan stdout ("\n Das Quadrat von " ++ (head (lines zahl)) ++ " ist: " ++ ausgabe ++ "!\n" )] where ausgabe = int2string ((string2int (head (lines zahl)))^2)(Das Pattern (read:_) darf erst ausgewertet werden, wenn der Request (ReadFile) abgesetzt wurde, deshalb mues lazy ausgewertet werden (s. Irrefutable Pattern))