7

重要な要素としてIORefを含むデータ型があります。showこれは、型クラスのメンバーにするためのクリーンな方法がないことを意味します。printこのタイプのIOモナドに関数があるので、これはそれほど悪くはありません。しかし、GHCiでは、これらのいずれかを返すたびに、表示できないというエラーが発生するという点で煩わしいです。

とにかくIOモナドで動作するGHCiに、IOアクションを使用して結果を表示させる方法はありますか?そうでない場合、書くことへの悪影響はありますshow a = unsafePerformIO $ print aか?

4

2 に答える 2

11

次のようなものを .ghci ファイルに追加することを検討しましたか?

instance (Show a) => Show (IORef a) where
    show a = show (unsafePerformIO (readIORef a))

まったく安全ではありませんが、これが個人的な使用のためだけであれば、おそらく問題ありません。

より一般的な使用のために、以前に与えられた答えは私には良さそうです。つまり、静的な "I can't show this" メッセージを定義します。

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"
于 2011-11-30T22:17:03.950 に答える
2

ghci には、戻り値の 3 つのケースがあります。

  1. Show a => a: show を実行して印刷するだけです
  2. Show a => IO a: アクションを実行し、show と print を実行します
  3. 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
于 2011-11-30T20:16:39.520 に答える