8 Stimmen

Gibt es eine polymorphe `toString` Funktion, die keine Anführungszeichen hinzufügt?

In den meisten OO-Sprachen, mit denen ich vertraut bin, ist die toString-Methode eines String tatsächlich nur die Identitätsfunktion. Aber in Haskell fügt show doppelte Anführungszeichen hinzu.

Also, wenn ich eine Funktion wie diese schreibe

f :: Show a => [a] -> String
f = concat . map show

funktioniert es wie erwartet für Zahlen

f [0,1,2,3]  -- "0123"

aber Strings enden mit zusätzlichen Anführungszeichen

f ["one", "two", "three"] -- "\"one\"\"two\"\"three\""

wenn ich eigentlich "onetwothree" möchte.

Wenn ich f polymorphisch schreiben wollte, gibt es eine Möglichkeit, dies nur mit einer Show-Einschränkung und ohne Überschreiben der Show-Instanz für String zu tun (wenn das überhaupt möglich ist).

Das Beste, was mir einfällt, ist, meine eigene Typklasse zu erstellen:

class (Show a) => ToString a where
   toString = show

und eine Instanz für alles hinzufügen?

instance ToString String where toString = id
instance ToString Char where toString = pure
instance ToString Int
instance ToString Maybe
...etc

8voto

Ben Punkte 62082

Ich denke, die eigentliche Ursache für dein Problem ist, dass show nicht wirklich renderToText ist. Es soll Text erzeugen, den du in Haskell-Code einfügen könntest, um den gleichen Wert zu erhalten, oder den Wert unter Verwendung von read zurückzuwandeln.

Zu diesem Zweck würde show "foo" = "foo" nicht funktionieren, weil show "1" = "1" und show 1 = "1", was Informationen verliert.

Die Operation, die du auf "foo" anwenden möchtest, um "foo" zu erhalten und auf 1 anzuwenden, um "1" zu erhalten, ist etwas anderes als show. show ist einfach kein Java-ähnliches toString.

Wenn ich das zuvor benötigt habe, habe ich tatsächlich meine eigene neue Typklasse erstellt und eine Menge von Dingen zu Instanzen davon gemacht und dann das anstelle von Show verwendet. Die meisten Instanzen wurden mit show implementiert, aber String war nicht der einzige, den ich anpassen wollte, also war die separate Typklasse nicht völlig verschwendet. In der Praxis habe ich festgestellt, dass es nur eine Handvoll Typen gab, für die ich tatsächlich die Instanz benötigte, und es war ziemlich trivial, sie hinzuzufügen, sobald ich Kompilierfehler bekam.

5voto

Mathnerd314 Punkte 191

Die Pretty-Klasse und ihr entsprechender Typ Doc haben das benötigte Verhalten für die Show-Funktion. Ihr Link zeigt jedoch einen anderen Anwendungsfall; vielleicht könnten Sie die Frage bearbeiten?

3voto

Tom Crockett Punkte 29618

Sie könnten dies tun:

{-# LANGUAGE FlexibleInstances, UndecidableInstances, OverlappingInstances #-}

class Show a => ToString a where 
    toString :: a -> String

instance Show a => ToString a where 
    toString = show

instance ToString String where 
    toString = id

Prelude> toString "hallo"
"hallo"
Prelude> toString 3
"3"

Beachten Sie, dass dies wahrscheinlich eine schreckliche Idee ist.

2voto

Cetin Sert Punkte 4353

Sie könnten newtype mit OverloadedStrings verwenden:

{-# LANGUAGE OverloadedStrings #-}

import           Data.ByteString.Char8      (ByteString)
import qualified Data.ByteString.Char8 as B

newtype LiteralString = LS ByteString
instance IsString LiteralString where fromString  = LS . B.pack
instance Show     LiteralString where show (LS x) = B.unpack x
instance Read     LiteralString where readsPrec p s = map (\(!s, !r) -> (LS s,r)) $! readsPrec p s

hello :: LiteralString
hello = "hello world"

main :: IO ()
main = putStrLn . show $! hello

output:

hello world

Die doppelten Anführungszeichen sind im Normalfall tatsächlich nützlich, wenn man eine gezeigte Zeichenfolge im Kontext eines größeren Ausdrucks zurückliest, da sie die gezeigten Zeichenfolgenwerte klar von Werten anderer gezeigter Typen abgrenzen:

x :: (ByteString, Int)
x =     read . show $!  ("go", 10)
--  Zeichenfolgenwert beginnt --^^-- endet

y :: (LiteralString, Int)
y =     read . show $!  ("go", 10) 
-- Zeichenfolgenwert beginnt --^       ^ verbraucht alle Zeichen; lesen scheitert

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X