只要你有这些类型的错误,如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,感谢您对素数算法的正确使用。 –