这里有些微妙之处可能会让您失望.与首次出现相反,其值:guard False <|> guard False不是通常意义上的_|_.相反,这是一个定义完善的IO操作,如果被执行,将不会在引发异常的意义上终止.但是,这种类型的非终止仍然有用,因为我们可以捕获它(例如,添加另一个<|>替代方法!).还要注意,因为您没有提供更好的异常,所以会抛出默认异常userError "mzero".如果您是通过以下方式导致失败的话:ioError (userError "one") <|> ioError (userError "two")您会看到,如果所有操作均失败,则抛出的最后一个异常是复合操作抛出的异常.This instance doesn't seem to behave properly:> guard True <|> guard False> guard False <|> guard False*** Exception: user error (mzero)One might argue that this cannot result in anything else. But why define such instance in the first place? Is there any good reason to result in _|_ whenever evaluation does not make sense? 解决方案 The purpose of the Alternative instance for IO is to combine IO actions that might fail (by causing an IO error or otherwise throwing an exception) into a single IO action that "tries" multiple actions in turn, accepting the first successful one, or -- if all actions fail -- fails itself.So, something like this would work to read one or more lines (using some) from standard input or else (using <|>) complain if no lines are available:main = (print =<< some getLine) <|> putStrLn "No input!"or you could write something like:readConfig :: IO ConfigreadConfig = readConfigFile "~/.local/myapp/config" <|> readConfigFile "/etc/myapp/config" <|> return defaultConfigGiven this, it makes perfect sense that:guard False <|> guard Falserepresents an action that, when executed, must fail by generating an exception. If it didn't, as @danidaz has pointed out, then executing the action:guard False <|> guard False <|> putStrLn "success!"wouldn't work to execute the third action. Since <|> is left associative and tries its left action before its right, executing the value of this expression would just execute whatever successful action guard False <|> guard False represented (e.g., return () or whatever) and never try putStrLn "success!".There's a subtlety here that may be throwing you off. Contrary to first appearances, the value of:guard False <|> guard Falseisn't _|_ in the usual sense. Rather it's a perfectly well defined IO action that, if executed will fail to terminate in the sense of throwing an exception. That type of non-termination is still useful, though, because we can catch it (by adding another <|> alternative, for example!).Also note, because you haven't supplied a better exception, a default exception of userError "mzero" is thrown. If you had instead caused failure via:ioError (userError "one") <|> ioError (userError "two")you'd see that if all actions fail, the last exception thrown is the one that gets thrown by the composite action. 这篇关于实例替代IO的目的是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 10-14 07:47