我正在尝试做一个返回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"
但我的错误是Couldn't match excepted type IO BOOL with actual type Bool In the return type of a call of "testOwlFile"
我能为此做些什么?
答案 0 :(得分:7)
一般来说,请避免考虑“转换”。有时您实际上需要这样做,但通常情况下,如果您正确使用,类型系统会在正确的位置为您提供正确的类型。
IO Bool
不是一个布尔值,但是一个可能与副作用一起产生布尔值的动作。那么为什么你要将一个非常好的纯值“转换”成这样一个动作,一个实际上没有做任何类型的东西的动作呢?这没有多大意义。正如已经说过的,正确的做法是直接使用该值;我只是把它直接放在if
条件下:
main = do
[src] <- getArgs
if src =~ owlFile
then ...
else ...
尽管如此,这种转换Bool -> IO Bool
无论多么无用,都是可能的。实际上,对于任何monad 1 m
,这是基本操作之一:
class Monad m where
return :: a -> m a
所以你原则上可以写
resTestOwlFile <- return testOwlFile
但不要。这总是等同于let resTestOwlFile = testOwlFile
(由monad laws保证)。
<小时/> 1 较弱的
Applicative
实际上已经足够了。
答案 1 :(得分:6)
问题是testOwlFile
的类型为Bool
,但<-
符号需要IO something
。
如果testOwlFile
确实有IO Bool
类型,则resTestOwlFile
的类型为Bool
,您的代码就可以正常运行。
正如@ user2407038在评论中指出的那样,当你定义的东西与你定义它的表达式具有相同的类型时,你可以使用let
而不是<-
:
let resTestOwlFile = testOwlFile
或者您可以直接在下一行的testOwlFile
语句中使用if
。
请注意,对于<-
类的m something
类的任何m
,Monad
符号通常需要m
,但在这种情况下{{1} }}必须是IO
,因为您正在定义main
函数,并且因为do
块中的其他代码,例如getArgs
和print
。< / p>