我有一個數據類型,其中包含一個IORef作爲一個重要的元素。這意味着沒有一種簡單的方法使其成爲show
類型類的成員。這並不算太壞,因爲我在這個類型的IO monad中有一個print
函數。但在GHCi中這是令人討厭的,因爲每次我返回其中一個結果時,我都會得到一個錯誤,指出它無法顯示。顯示IO類型
有沒有辦法讓GHCi在IO monad中運行,使用IO操作來顯示結果?如果沒有,編寫show a = unsafePerformIO $ print a
會有什麼不利後果?
我有一個數據類型,其中包含一個IORef作爲一個重要的元素。這意味着沒有一種簡單的方法使其成爲show
類型類的成員。這並不算太壞,因爲我在這個類型的IO monad中有一個print
函數。但在GHCi中這是令人討厭的,因爲每次我返回其中一個結果時,我都會得到一個錯誤,指出它無法顯示。顯示IO類型
有沒有辦法讓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"
請注意,這些'ShowIO'實例需要OverlappingInstances擴展。雖然可能比'unsafePerformIO'更少,這是相當不妥的。肯定有助於發展。 –
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
據我所知,有沒有辦法告訴ghci使用與'show'不同的功能來顯示結果。但是,您可以爲數據類型定義一個show實例,該實例只顯示「」或類似的ioref。如果不太方便,那可能會比使用'unsafePerformIO'更簡潔。 –
sclv