Покажите для типов IO
-
26-10-2019 - |
Вопрос
У меня есть тип данных, который содержит IOREF в качестве важного элемента. Это означает, что нет чистого способа сделать его членом show
Тип класса. Это не так уж плохо, так как у меня есть print
Функция в IO Monad для этого типа. Но в GHCI это раздражает, что каждый раз, когда я возвращаю одну из этих вещей в результате, я получаю ошибку, утверждая, что ее нельзя показать.
Есть ли способ получить GHCI, который в любом случае работает в IO Monad, чтобы использовать действие IO, чтобы показать результат? Если нет, то будут ли какие -либо негативные последствия для написания show a = unsafePerformIO $ print a
?
Решение
Считали ли вы добавить в свой файл .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"
Или используйте пользовательскую функцию. Я предлагаю сделать класс и поднять все экземпляры шоу:
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 ()
: ничего не печатайте
Поэтому обычно, если вы вводите действие ввода -вывода, оно выполняется, и результат печатается, если оно не ()
. Анкет Давай попробуем:
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