Afficher pour les types IO
-
26-10-2019 - |
Question
I ont un type de données qui contient un IORef comme un élément important. Cela signifie qu'il n'y a pas une manière propre à en faire un membre de la classe de type show
. Ce n'est pas trop mal que j'ai une fonction print
dans la monade IO pour ce type. Mais il est gênant dans GHCi en ce que chaque fois que je retourne une de ces choses à la suite je reçois une erreur indiquant qu'il ne peut pas être affichée.
Y at-il un moyen d'obtenir GHCi, qui fonctionne dans la monade IO de toute façon, d'utiliser une action IO pour afficher un résultat? Dans le cas contraire, aurait-il des conséquences négatives pour l'écriture show a = unsafePerformIO $ print a
?
La solution
Avez-vous envisagé d'ajouter à votre fichier .ghci quelque chose comme:
instance (Show a) => Show (IORef a) where
show a = show (unsafePerformIO (readIORef a))
Il est pas sûr du tout, mais si cela est juste pour votre usage personnel peut-être est OK.
Pour une utilisation plus générale les réponses déjà données me semblent bonnes. C'est, soit définir une statique « Je ne peux pas montrer » message:
instance Show (IORef a) where
show _ = "<ioref>"
Cela donnerait quelque chose comme:
> runFunc
MyStruct <ioref> 4 "string val"
Ou utiliser une fonction personnalisée. Je suggère faire une classe et la levée de toutes les instances Afficher:
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
Donner la sortie (non testé, ce n'est écrit à la main):
> myFunc >>= showIO
MyStruct "My String in an IORef" 4 "string val"
Autres conseils
ghci a trois cas pour les valeurs de retour:
-
Show a => a
: Il suffit de lancer show et l'imprimer -
Show a => IO a
: Exécutez l'action, exécutez visualiser et imprimer -
IO ()
: rien d'impression
Donc, en général, si vous tapez une action IO, il get exécuté et le résultat est imprimé si ce n'est pas ()
. Essayons:
ghci>15
15
ghci>'a' : 'b' : 'c' : []
"abc"
ghci>putStrLn "Hello, world!"
Hello, world!
ghci>putStrLn "Hello, world!" >> return 42
Hello, world!
42
ghci>
Si vous voulez imprimer quelque chose de différent, la meilleure façon est probablement écrire une fonction personnalisée et le coller devant chaque ligne que vous voulez voir:
myShowFun :: ... -> IO String
ghci> myShowFun $ ...
foobar