Mostra per i tipi di IO
-
26-10-2019 - |
Domanda
Ho un tipo di dati che contiene un IOREF come un elemento importante. Ciò significa che non v'è un modo pulito per renderlo un membro della classe di tipo show
. Questo non è troppo male come Ho una funzione print
nella monade IO per questo tipo. Ma è fastidioso in GHCi in quanto ogni volta che ritorno uno di questi cosa come un risultato che ottengo un errore che indica che non può essere mostrato.
C'è un modo per ottenere GHCi, che opera nel IO Monade in ogni caso, per utilizzare un'azione IO per mostrare un risultato? In caso contrario, ci sarebbero conseguenze negative per la scrittura show a = unsafePerformIO $ print a
?
Soluzione
Avete considerato di aggiungere al vostro file di qualcosa di simile .ghci:
instance (Show a) => Show (IORef a) where
show a = show (unsafePerformIO (readIORef a))
Non è sicuro a tutti, ma se questo è solo per uso personale, forse che è OK.
Per l'uso più generale le risposte date in precedenza guardare bene a me. Cioè, sia definire una statica "non posso mostrare questo" messaggio:
instance Show (IORef a) where
show _ = "<ioref>"
Questo darebbe qualcosa di simile:
> runFunc
MyStruct <ioref> 4 "string val"
o utilizzare una funzione personalizzata. Suggerisco di fare una classe e sollevare tutte le istanze Mostra:
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
Dare l'uscita (non testato, questo è solo scritto a mano):
> myFunc >>= showIO
MyStruct "My String in an IORef" 4 "string val"
Altri suggerimenti
ghci ha tre casi per i valori di ritorno:
-
Show a => a
: basta eseguire spettacolo e stamparlo -
Show a => IO a
: eseguire l'azione, corsa spettacolo e Stampa -
IO ()
: print niente
Quindi, di solito, se si digita l'azione IO, di venire di eseguita e il risultato viene stampato se non è ()
. Proviamo:
ghci>15
15
ghci>'a' : 'b' : 'c' : []
"abc"
ghci>putStrLn "Hello, world!"
Hello, world!
ghci>putStrLn "Hello, world!" >> return 42
Hello, world!
42
ghci>
Se si desidera stampare qualcosa di diverso, il modo migliore è probabilmente quello di scrivere una funzione personalizzata e bastone di fronte a ogni riga che si desidera visualizzare:
myShowFun :: ... -> IO String
ghci> myShowFun $ ...
foobar