我只是在写一小段代码,我想在IO Monad中使用guard function。然而,存在no definition of MonadPlus for IO,这意味着我们不能在IO域中使用guard。我已经看到了an example of using the MabyeT transformer to use guard in the Maybe Monad,然后提升了所有IO操作,但如果没有必要的话,我并不真的想这样做。
我想要的一些例子可能是:
handleFlags :: [Flag] -> IO ()
handleFlags flags = do
when (Help `elem` flags) (putStrLn "Usage: program_name options...")
guard (Help `elem` flags)
... do stuff ...
return ()我想知道是否有一种很好的方法可以通过声明MonadPlus或其他方式在IO Monad中获得一个守卫函数(或类似的函数)。或者我可能做错了;有没有更好的方法在上面的函数中编写帮助消息?谢谢。
(附注:我可以使用if-then-else语句,但它似乎以某种方式违背了要点。更不用说,对于许多选项,这将导致大量的嵌套。)
发布于 2010-12-22 07:06:58
考虑MonadPlus的定义
class Monad m => MonadPlus m where
mzero :: m a
mplus :: m a -> m a -> m a您将如何为IO实现mzero?IO a类型的值表示返回a类型的内容的IO计算,因此mzero必须是返回任何可能类型的内容的IO计算。显然,没有办法为某个任意类型变出一个值,而且与Maybe不同的是,我们没有可以使用的“空”构造函数,因此mzero必然表示永远不返回的IO计算。
如何编写永远不返回的IO计算?基本上,要么进入无限循环,要么抛出运行时错误。前者的效用令人怀疑,因此后者就是你所坚持的。
简而言之,要为IO编写一个MonadPlus实例,您需要做的是:让mzero抛出一个运行时异常,并让mplus在捕获mzero抛出的任何异常时计算其第一个参数。如果未引发异常,则返回结果。如果引发异常,则在忽略异常的情况下计算mplus的第二个参数。
也就是说,运行时异常通常被认为是不可取的,所以在走这条路之前我会犹豫。如果您确实想这样做(并且不介意增加您的程序在运行时崩溃的可能性),您可以找到在Control.Exception中实现上述内容所需的一切。
在实践中,如果我想要对一元表达式求值的结果进行大量的guard运算,或者如果大多数条件依赖于作为函数参数提供的纯值(示例中的标志是),我可能会使用一元转换器方法,就像@Anthony的答案中那样使用模式保护。
发布于 2010-12-22 07:05:50
我和守卫一起做这类事情。
handleFlags :: [Flag] -> IO ()
handleFlags flags
| Help `elem` flags = putStrLn "Usage: program_name options..."
| otherwise = return ()发布于 2016-05-01 23:17:41
有一些函数正是为此而设计的:在Control.Monad中,函数when和它的对应函数unless。安东尼的答案可以重写为:
handleFlags :: [Flag] -> IO ()
handleFlags flags =
when (Help `elem` flags) $ putStrLn "Usage: program_name options..."规格:
when :: (Applicative m) => Bool -> m () -> m ()
unless bool = when (not bool)Link to docs on hackage.haskell.org
如果需要更多,这里有一个link to another package, specifically monad-oriented and with several more utilities: Control.Monad.IfElse
https://stackoverflow.com/questions/4504489
复制相似问题