Show für IO -Typen
-
26-10-2019 - |
Frage
Ich habe einen Datentyp, der ein IOREF als wichtiges Element enthält. Dies bedeutet, dass es keinen sauberen Weg gibt, um es zu einem Mitglied der show
Geben Sie Klasse ein. Das ist nicht schlecht, da ich eine habe print
Funktion im IO -Monad für diesen Typ. Bei GHCI ist es jedoch ärgerlich, dass ich jedes Mal, wenn ich eines dieser Dinge zurückgibt, einen Fehler, der besagt, dass es nicht angezeigt werden kann.
Gibt es eine Möglichkeit, GHCI zu bekommen, der sowieso in der IO -Monadin arbeitet, um eine IO -Aktion zu verwenden, um ein Ergebnis zu zeigen? Wenn nicht, gäbe es negative Konsequenzen für das Schreiben show a = unsafePerformIO $ print a
?
Lösung
Haben Sie darüber nachgedacht, Ihre .ghci -Datei hinzuzufügen, so etwas wie:
instance (Show a) => Show (IORef a) where
show a = show (unsafePerformIO (readIORef a))
Es ist überhaupt nicht sicher, aber wenn dies nur für Ihren persönlichen Gebrauch ist, ist das vielleicht in Ordnung.
Um allgemeiner zu verwenden, sehen Sie die zuvor gegebenen Antworten für mich gut aus. Das heißt, entweder definieren Sie eine statische "Ich kann diese" -Meldung nicht zeigen:
instance Show (IORef a) where
show _ = "<ioref>"
Dies würde so etwas geben wie:
> runFunc
MyStruct <ioref> 4 "string val"
Oder verwenden Sie eine benutzerdefinierte Funktion. Ich schlage vor, eine Klasse zu erstellen und alle Showinstanzen zu heben:
class ShowIO a where
showIO :: a -> IO String
instance Show a => ShowIO a where
showIO = return . show
instance ShowIO a => ShowIO (IORef a) where
showIO a = readIORef a >>= showIO
Wenn Sie die Ausgabe geben (ungetestet, ist dies nur handgeschrieben):
> myFunc >>= showIO
MyStruct "My String in an IORef" 4 "string val"
Andere Tipps
GHCI hat drei Fälle für Rückgabewerte:
Show a => a
: Führen Sie einfach Show aus und drucken Sie sie ausShow a => IO a
: Führen Sie die Aktion aus, führen Sie Show aus und drucken Sie sieIO ()
: Drucken Sie nichts
Wenn Sie also eine IO -Aktion eingeben, wird normalerweise ausgeführt und das Ergebnis wird gedruckt, wenn dies nicht der Fall ist ()
. Lass es uns versuchen:
ghci>15
15
ghci>'a' : 'b' : 'c' : []
"abc"
ghci>putStrLn "Hello, world!"
Hello, world!
ghci>putStrLn "Hello, world!" >> return 42
Hello, world!
42
ghci>
Wenn Sie etwas anderes ausdrucken möchten, besteht der beste Weg wahrscheinlich, eine benutzerdefinierte Funktion zu schreiben und sie vor jede Zeile zu stecken, die Sie sehen möchten:
myShowFun :: ... -> IO String
ghci> myShowFun $ ...
foobar