Показать для типов ввода-вывода
У меня есть тип данных, который содержит IORef в качестве важного элемента. Это означает, что нет чистого способа сделать его членом show
тип класс. Это не так уж плохо, так как у меня есть print
функция в монаде IO для этого типа. Но в GHCi раздражает то, что каждый раз, когда я возвращаю одну из этих вещей, в результате я получаю сообщение о том, что она не может быть показана.
Есть ли способ заставить GHCi, который все равно работает в монаде ввода-вывода, использовать действие ввода-вывода, чтобы показать результат? Если нет, будут ли какие-либо негативные последствия для написания show a = unsafePerformIO $ print a
?
2 ответа
Рассматривали ли вы добавить в свой файл.ghci что-то вроде:
instance (Show a) => Show (IORef a) where
show a = show (unsafePerformIO (readIORef a))
Это совсем не безопасно, но если это только для вашего личного использования, возможно, это нормально.
Для более общего использования ранее приведенные ответы выглядят хорошо для меня. То есть либо определите статическое сообщение "Я не могу показать это":
instance Show (IORef a) where
show _ = "<ioref>"
Это даст что-то вроде:
> runFunc
MyStruct <ioref> 4 "string val"
Или используйте пользовательскую функцию. Я предлагаю сделать урок и снять все экземпляры Show:
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
Предоставление вывода (не проверено, это просто написано от руки):
> myFunc >>= showIO
MyStruct "My String in an IORef" 4 "string val"
У ghci есть три случая для возвращаемых значений:
Show a => a
: Просто запустите шоу и распечатайте егоShow a => IO a
: Выполнить действие, запустить шоу и распечататьIO ()
ничего не печатать
Так что обычно, если вы вводите IO-действие, оно выполняется и результат печатается, если это не так. ()
, Давай попробуем:
ghci>15
15
ghci>'a' : 'b' : 'c' : []
"abc"
ghci>putStrLn "Hello, world!"
Hello, world!
ghci>putStrLn "Hello, world!" >> return 42
Hello, world!
42
ghci>
Если вы хотите напечатать что-то другое, лучше всего написать собственную функцию и поместить ее перед каждой строкой, которую вы хотите увидеть:
myShowFun :: ... -> IO String
ghci> myShowFun $ ...
foobar