【发布时间】:2018-06-10 11:17:20
【问题描述】:
我不明白为什么下面的代码会这样:
myand :: Bool -> Bool -> Bool
myand True True = True
myand _ _ = False
containsAandB :: String -> IO Bool
containsAandB s = do
containsA <- do
putStrLn $ "Check if 'a' is in " ++ s
return $ 'a' `elem` s
containsB <- do
putStrLn $ "Check if 'b' is in " ++ s
return $ 'b' `elem` s
return $ containsA `myand` containsB
这是我测试函数时的输出:
*Main> containsAandB "def"
Check if 'a' is in def
Check if 'b' in in def
False
注意 (&&) 的行为就像 'myand',我只是编写了一个自定义函数来更好地可视化正在发生的事情。
我对'Check if 'b' is in def 部分感到惊讶,因为containsA 已经是错误的,因此无论containsB 如何都可以评估“myand”。
问题 1:containsB 也必须被评估是否有特殊原因?我的理解是,除非需要,否则不会评估 containsB <- do ... 语句,但我的猜测是,它的行为可能会有所不同,因为它是 IO,因此不会没有副作用?
问题 2:
在不处理嵌套的if-else 子句的情况下,获得所需行为的最佳实践方法是什么(如果containsA 为假,则未选中containsB)?
【问题讨论】:
-
好吧,你把它包装在一个
IOmonad 中,所以由于 monad。 -
好的,所以我的假设是正确的,因为它没有副作用,所以它的行为方式是正确的?很抱歉,这条评论有点含糊,我无法理解。
-
想象一下你的两个元素
containsA和containsB从一个文件中读取。然后他们推进光标。现在这意味着根据containsA的值,光标会(或不会)前进?这是人们通常想要避免的行为。因此,如果IO动作在 monad 中,它们就可以保证发生。