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 IOError
wobei IOError eine der folgenden Formen annehmen kann:
WriteError String
ReadError String
SearchError String
FormatError String
OtherError String
Mö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))