Ich habe vor etwa vier Monaten mit dem Programmieren in Haskell angefangen und jetzt bin ich an den Punkt gekommen, wo ich mich mit dem IO-System von Haskell beschäftigen muss. Ich habe bereits viele IO-Aktionen durchgeführt und hatte keine Probleme, die ich selbst nicht lösen konnte, aber dieses Mal googelte ich fast zwei Stunden lang ohne Erfolg, um Informationen über die Funktion readMaybe zu erhalten. Also habe ich das folgende Problem zu lösen und ich habe bereits viele verschiedene Ansätze versucht, um es zu lösen, aber die ganze Zeit bekomme ich die gleiche Fehlermeldung von meinem Compiler:
%Vor%Ich verstehe, was der Compiler mir sagen will, aber ich habe keine Ahnung, wie ich dieses Problem lösen soll. Ich habe bereits versucht, eine Klassenbeschränkung hinzuzufügen, aber ohne Erfolg. Also hier ist mein sehr kleines und einfaches Programm, das nur zählt, wie viele gültige Zahlen der Benutzer eingegeben hat. Das Programm soll beendet werden, wenn der Benutzer eine leere Zeile eingibt. Dies ist nur eine Hilfsfunktion, die ich später für mein Projekt verwenden möchte.
%Vor%Leider konnte ich nicht viele Informationen über die Funktion readMaybe herausfinden. Das einzige, was ich finden konnte, war in der Haskell-Bibliothek Text.Read:
%Vor%Das sehr Seltsame für mich ist, dass ich bereits eine solche Funktion geschrieben habe, die die readMaybe-Funktion verwendet und es hat perfekt funktioniert ... Dieses Programm fragt den Benutzer nur nach einer Nummer und fragt weiter, solange der Benutzer eine gültige Nummer eingibt
%Vor%Soweit ich sehen kann, gibt es keine Unterschiede zwischen der Verwendung der Funktion readMaybe in den beiden Programmen und deshalb funktioniert sie in der einen, aber nicht in der anderen:)
Ich wäre wirklich dankbar für Hinweise von dir !!
Das hat nichts mit IO zu tun, also verstehen Sie vielleicht nicht, was der Compiler Ihnen zu sagen versucht. Es gibt eine Typvariable a
in readMaybe
's Signatur; a
muss eine Read
Instanz haben, aber ansonsten kann es alles sein. Der Compiler sagt Ihnen, dass es keine Möglichkeit gibt zu bestimmen, was a
sein soll.
In getLineInt
haben Sie dieses Problem nicht, weil Sie das Ergebnis von readMaybe
zurückgeben und die Typensignatur sagt, dass es Int
sein sollte. In countNumbers
verwenden Sie nicht das Ergebnis von readMaybe
. Es gibt also keine Möglichkeit, den richtigen Typ zu ermitteln. Sie können dies beheben, indem Sie eine explizite Typ-Signatur hinzufügen (Ich habe Int
ausgewählt, da Sie anscheinend Zahlen zählen):
Endlich ein Wort über do
notation: es ist nur syntaktischer Zucker, du musst es nicht ständig benutzen. Anstelle von do return x
können Sie einfach return x
und statt
Sie können einfach
tun %Vor%Das macht die Dinge lesbarer:
%Vor% In Ihrer zweiten Funktion ist klar, dass readMaybe line
als String -> Maybe Int
verwendet wird, da Typinferenz bemerkt, dass Sie return x
und daher x
ein Int
verwenden müssen.
In Ihrer ersten Funktion verwenden Sie den Wert Maybe
überhaupt nicht, Sie möchten nur überprüfen, ob read
erfolgreich war. Da Sie jedoch den Typ (weder explizit noch implizit mit Typinferenz) angegeben haben, ist die Typvariable nicht eindeutig:
Es gibt eine einfache Lösung: Kommentieren Sie den Typ:
%Vor% Dies ist übrigens genau das gleiche Verhalten, das Sie bei der Verwendung von read
in ghci
ohne einen Kontexttyp kennen:
Sobald Sie den Typ klar machen, ist alles in Ordnung:
%Vor% Nun, da wir gesehen haben, warum der Fehler passiert, machen wir dieses Programm viel einfacher. Zuerst verwenden wir eine benutzerdefinierte readMaybe
:
Nun, wie zählt man Zahlen? Zahlen sind die Wörter, bei denen readMaybeInt
nicht Nothing
zurückgibt:
Wie berechnet man nun die Zahlen in der Standardeingabe? Wir nehmen einfach die Eingabe, bis eine Zeile vollständig leer ist, map countNumbers
für alle diese Zeilen und dann sum
:
Wenn Sie nicht an die Bind-Methoden gewöhnt sind, ist das im Grunde
%Vor%Alles in allem erhalten wir die folgende knappe Lösung:
%Vor% Jetzt gibt es nur noch eine Funktion, die in der IO-Monade arbeitet, und alle Funktionen sind grundsätzlich Anwendungen von Standardfunktionen. Beachten Sie, dass getContents
das Handle für die Standardeingabe schließt. Wenn Sie verwenden möchten, verwenden Sie besser etwas wie
, die Zeilen extrahiert, bis eine Zeile mit delim
gefunden wurde. Beachten Sie, dass Sie in diesem Fall lineNumberCount
ändern müssen:
Tags und Links haskell