我正在尝试做一个返回true或false的函数.
owlFile = ".+\\.owl"
testOwlFile src = src =~ owlFile :: Bool
我需要在我的阻止上使用:
main = do
[src] <- getArgs
resTestOwlFile <- testOwlFile
if resTestOwlFile
then do ontology <- runX(readDocument [withValidate no,withRemoveWS yes ] src >>> getontology)
else print "error"
Run Code Online (Sandbox Code Playgroud)
但我有一个错误 Couldn't match excepted type IO BOOL with actual type Bool In the return type of a call of "testOwlFile"
我该怎么办?
一般来说,请避免考虑"转换".有时您实际上需要这样做,但通常类型系统如果您正确使用它,则会在正确的位置为您提供正确的类型.
IO Bool是不是一个布尔值,而是一个动作,与副作用可能一起,也将产生一个布尔值.那么为什么你要将一个非常好的纯值"转换"成这样一个动作,一个实际上没有做任何类型的东西的动作呢?这没有多大意义.正如已经说过的,正确的做法是直接使用该值; 我只是把它直接放在if条件中:
main = do
[src] <- getArgs
if src =~ owlFile
then ...
else ...
Run Code Online (Sandbox Code Playgroud)
也就是说,这种转换Bool -> IO Bool无论多么无用,都是可能的.实际上,对于任何monad 1来说 m,这是基本操作之一:
class Monad m where
return :: a -> m a
Run Code Online (Sandbox Code Playgroud)
所以你原则上可以写
resTestOwlFile <- return testOwlFile
Run Code Online (Sandbox Code Playgroud)
但不要.这总是相当于let resTestOwlFile = testOwlFile(由monad法律保证).
Applicative实际上已经足够了.
问题是testOwlFile类型Bool,但<-符号期望一个IO something.
如果testOwlFile确实有类型IO Bool,那么resTestOwlFile将有类型Bool,你的代码将建立良好.
正如@ user2407038在注释中指出的那样,您可以使用let而不是<-在您定义的事物与您使用它定义的表达式具有相同类型时:
let resTestOwlFile = testOwlFile
Run Code Online (Sandbox Code Playgroud)
或者你可以testOwlFile直接if在下一行的语句中使用.
注意,更一般地说,<-符号期望m something任何m一个Monad类的实例,但在这种情况下m必须是IO因为你正在定义main函数,并且因为do块中的其他代码像getArgs和print.