只要你有這些類型的錯誤,如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
功能,將滿足型檢查。它將不得不採取一個字符串(你的調試信息)和一個布爾(你的結果),只評估布爾。
debug :: String -> Bool -> Bool
debug = undefined
但是,如果我們嘗試實現它,它那種不工作,因爲我們無法逃避的IO單子,因爲putStrLn的類型是putStrLn :: String -> IO()
。爲了將其與評估的Bool
結合起來,我們將不得不把Bool
在IO
的背景太:
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
有我們需要的類型。
所以,現在我們可以實施在debugIO
方面我們debug
功能:
debug :: String -> Bool -> Bool
debug s r = unsafePerformIO $ debugIO s r
這實際上是相當多的,你跟在Debug.Trace
包trace
功能得到什麼作爲已經指出的FUZxxl。
而且由於我們同意不應該使用unsafePerformIO
,所以使用trace
函數是首選。請記住,儘管它是純粹的類型簽名,但它實際上也是而不是參照透明並使用unsafePerformIO
下面。
你爲什麼在取平方根之前從'n'中減去1?這隻適用於不是質數平方的數字,並且會失敗,例如25。 – jwodder
@jwodder,感謝您對素數算法的正確使用。 –