Warum gibt Haskells Prelude.read kein Vielleicht zurück?

108

Gibt es einen guten Grund, warum die Art von Prelude.read ist

read :: Read a => String -> a

anstatt einen MaybeWert zurückzugeben?

read :: Read a => String -> Maybe a

Wäre letzteres nicht natürlicher, da die Zeichenfolge möglicherweise nicht analysierbar ist, Haskell?

Oder sogar eine Either String a, wo Leftwürde die ursprüngliche Zeichenfolge enthalten, wenn sie nicht analysiert würde, und Rightdas Ergebnis, wenn dies der Fall wäre?

Bearbeiten:

Ich versuche nicht, andere dazu zu bringen, einen entsprechenden Wrapper für mich zu schreiben. Ich suche nur die Bestätigung, dass dies sicher ist.

Bilal Barakat
quelle
14
Warum takeakzeptiert keine Num a => a? Warum gibt es einen Sonderfall fmapfür Listen? Warum ist Functorfür MonadInstanzen nicht erforderlich ? Ich erwarte, dass die Antwort den Antworten auf diese und verwandte Fragen ähnlich ist.
3
Nun, deshalb habe ich es so formuliert, wie ich es getan habe, und die Option offen gelassen, dass es keinen guten Grund gibt. Ich vermute auch, dass dies nicht der Fall ist, wie bei den bekannten Beispielen, die Sie geben. Es lohnt sich jedoch zu fragen, ob das Schreiben meines eigenen Wrappers keine unvorhergesehenen Probleme nach sich zieht.
Bilal Barakat
Ich hoffe readMaybe, dass bald eine Funktion hinzugefügt wird.
August
Gute Punkte @delnan, sollte aber nicht takesein Integral n => n -> [a] -> [a]?
Doug McClean
@DougMcClean: Ja, es sollte eigentlich sein Integral, nicht Num- Hirnfurz.

Antworten:

106

Bearbeiten : Ab GHC 7.6 readMaybeist das Text.ReadModul im Basispaket verfügbar , zusammen mit readEither: http://hackage.haskell.org/packages/archive/base/latest/doc/html/Text-Read.html#v: readMaybe


Gute Frage! Die Art des Lesens selbst ändert sich nicht so schnell, da dies viele Dinge kaputt machen würde. Es sollte jedoch eine maybeReadFunktion geben.

Warum gibt es nicht? Die Antwort lautet "Trägheit". Es gab eine Diskussion in '08, die durch eine Diskussion über "scheitern" entgleist wurde.

Die gute Nachricht ist, dass die Leute ausreichend überzeugt waren, um nicht in den Bibliotheken zu scheitern. Die schlechte Nachricht ist, dass der Vorschlag im Shuffle verloren gegangen ist. Es sollte eine solche Funktion sein, obwohl man ist einfach zu schreiben (und es gibt Myriaden von sehr ähnliche Versionen im Umlauf viele Codebases).

Siehe auch diese Diskussion .

Persönlich verwende ich die Version aus dem sicheren Paket .

sclv
quelle
30

Ja, es wäre praktisch mit einer Lesefunktion, die Vielleicht zurückgibt. Sie können selbst eine erstellen:

readMaybe :: (Read a) => String -> Maybe a
readMaybe s = case reads s of
              [(x, "")] -> Just x
              _ -> Nothing
August
quelle
3
Danke dir! Ich hoffe, die Bearbeitung klingt nicht undankbar! :) Ich möchte nur klarstellen, dass ich nicht aus Faulheit frage ...
Bilal Barakat
6
Wenn @augustss es nicht bereitstellen kann, gibt es möglicherweise keine bessere Antwort.
John L
2
Ich glaube nicht, dass eine ursprüngliche Version jemals im ursprünglichen Design besprochen wurde. Viele dieser Dinge werden mit der Erfahrung offensichtlich, können aber schwer vorherzusagen sein.
August
Der Grund für das Lesen einer Liste ist der Fall, in dem mehrere gültige Parses vorhanden sind. Der Vielleicht-Fall liegt zwischen Lesen und Lesen.
Chris Kuklewicz
Ich denke, dies erfordert Read aTypklasse:readMaybe :: Read a => String -> Maybe a
David Tchepak
15

Abgesehen von Trägheit und / oder sich ändernden Einsichten könnte ein weiterer Grund sein, dass es ästhetisch ansprechend ist, eine Funktion zu haben, die als eine Art Umkehrung von wirken kann show. Das heißt, Sie möchten, dass dies read . showdie Identität ist (für Typen, die eine Instanz von Showund sind Read) und dass dies show . readdie Identität im Bereich von show(dh show . read . show == show) ist.

Ein Maybein der Art von readbricht die Symmetrie mit show :: a -> String.

yatima2975
quelle
Vielen Dank, dass Sie einen neuen Blickwinkel hinzugefügt haben! Das macht Sinn. Aber um dies sauber zu erreichen, wäre es nicht sinnvoll, wenn sowohl Show als auch Read einen bestimmten Typ erzeugen, z. B. "ParseableString"?
Bilal Barakat
1
@BilalBarakat: Der eindeutige Typ könnte sein newtype ValidShow a = ValidShow String. Der Phantomtyp macht es typsicherer.
Yairchu
9
Es ist ein interessanter Punkt, aber letztendlich eine falsche Symmetrie. Programmierer sollten Korrektheit über Ästhetik legen.
Matt Fenwick
1
@yairchu Es war mir nicht sofort klar, was Sie mit dem Phantomtyp meinten, also werde ich klären, falls jemand anders so verwirrt ist wie ich. Sie beabsichtigen so etwas wie showThing :: Show a => a -> ValidShow aund readThing :: Read a => ValidShow a -> a, damit der Typ des angezeigten Objekts im ValidShow-Objekt gespeichert wird. Auf diese Weise können Sie nicht schreiben readThing (showThing True) :: String.
Amalloy
12

Wie @augustss hervorhob, können Sie Ihre eigene sichere Lesefunktion erstellen. Jedoch seinreadMaybe stimmt jedoch nicht vollständig mit dem Lesen überein, da Leerzeichen am Ende eines Strings nicht ignoriert werden. (Ich habe diesen Fehler einmal gemacht, ich erinnere mich nicht ganz an den Kontext)

Wenn wir uns die Definition des Lesens im Haskell 98-Bericht ansehen, können wir sie so ändern, dass sie eine implementiert readMaybe, die perfekt mit dem übereinstimmt. readDies ist nicht allzu unpraktisch, da alle Funktionen, von denen es abhängt, im Prelude definiert sind:

readMaybe        :: (Read a) => String -> Maybe a
readMaybe s      =  case [x | (x,t) <- reads s, ("","") <- lex t] of
                         [x] -> Just x
                         _   -> Nothing
lpsmith
quelle
1
Vielen Dank! +1 für die Benachrichtigung über das Leerzeichenproblem, das zuvor nicht explizit angegeben wurde.
Bilal Barakat
3
Beachten Sie, dass Sie, wenn Sie nur das safePaket verwenden, eine korrekte Version von readMaybeverfügbar erhalten (es heißt readMayund ist identisch mit dieser Version.
Neil Mitchell
8

Diese Funktion (aufgerufen readMaybe) befindet sich jetzt im Haskell-Vorspiel! (Stand der aktuellen Basis - 4.6)

amindfv
quelle
2
Nun, der verlinkte Text sagt, dass es in Text.Read und nicht in Prelude ist (möglicherweise geändert), aber es hat mir trotzdem geholfen!
Kapichu