このような型エラーが発生Couldn't match expected type X with actual type Yした場合は、haskell 型システムを使用してガイドする必要があります。
それでは、何が問題なのか見てみましょう。
タイプ の純粋な関数がありInt -> Boolます。そして、明らかに純粋ではない(つまりIO Monadに存在する)デバッグ出力を出力したいとします。
とにかく、あなたが書きたいのはs.thです。それらの線に沿って:
foo x
| x > 0 = debug "ok" True
| otherwise = debug "ohhh...no" False
それでも、関数のタイプはfoo :: Int -> Bool
debugそれでは、型チェッカーを満たす関数を定義しましょう。String (デバッグ メッセージ) と Bool (結果) を受け取り、Bool にのみ評価する必要があります。
debug :: String -> Bool -> Bool
debug = undefined
しかし、それを実装しようとすると、 putStrLn の型が であるため IO モナドをエスケープできないため、機能しませんputStrLn :: String -> IO ()。それを a への評価と組み合わせるには、 the ものコンテキストにBool入れる必要があります。BoolIO
debugIO msg result = putStrLn msg >> return result
では、この関数の型を ghci に聞いてみましょう:
Main> :t debugIO
debugIO :: String -> b -> IO b
したがって、 を取得しますIO Boolが、必要なのはBool.
タイプの関数はありIO b -> bますか?hoogleで簡単に調べると、ヒントが得られます。
悪名高いunsafePerformIO :: IO a -> aには、ここで必要なタイプがあります。
これで、関数を次のように実装できます。debugdebugIO
debug :: String -> Bool -> Bool
debug s r = unsafePerformIO $ debugIO s r
これは実際には、FUZxxl によって既に指摘されているようtraceに、パッケージ内の関数で得られるものとほぼ同じです。そして、関数の使用法を決して使用してはならないこと
に同意するので、優先されます。純粋な型シグネチャであるにもかかわらず、実際には参照透過ではなく、その下で使用されることに注意してください。Debug.Trace
unsafePerformIOtraceunsafePerformIO