Rob*_*oli 13 io monads haskell guard
我只是写了一小段代码,我想在IO Monad中使用guard功能.但是,没有MonadPlus for IO的定义,这意味着我们不能在IO 域中使用guard.我已经看到了使用MabyeT变换器在Maybe Monad中使用guard然后解除所有IO操作的示例,但如果我不需要,我真的不想这样做.
我想要的一些例子可能是:
handleFlags :: [Flag] -> IO ()
handleFlags flags = do
when (Help `elem` flags) (putStrLn "Usage: program_name options...")
guard (Help `elem` flags)
... do stuff ...
return ()
Run Code Online (Sandbox Code Playgroud)
我想知道是否有一种很好的方法可以通过MonadPlus声明或其他方式在IO Monad中获得一个保护功能(或类似的东西).或许我做错了; 有没有更好的方法在上面的函数中编写帮助消息?谢谢.
(PS我可以使用if-then-else语句,但它似乎以某种方式打败了这一点.更不用说对于很多选项,它将导致大量的嵌套.)
C. *_*ann 23
考虑以下定义MonadPlus
:
class Monad m => MonadPlus m where
mzero :: m a
mplus :: m a -> m a -> m a
Run Code Online (Sandbox Code Playgroud)
你将如何实现mzero
的IO
?类型的值IO a
表示返回类型的IO计算a
,因此mzero
必须是返回任何可能类型的IO计算.显然,没有办法变出一些任意类型的值,而不像Maybe
有没有"空"构造,我们可以使用,这样mzero
会一定代表永远不会返回一个IO计算.
你如何编写一个永不返回的IO计算?基本上,要么进入无限循环,要么抛出运行时错误.前者具有可疑的效用,所以后者就是你所坚持的.
简而言之,MonadPlus
为IO
你所做的事情编写一个实例是:mzero
抛出一个运行时异常,并mplus
在捕获任何异常时评估它的第一个参数mzero
.如果没有引发异常,则返回结果.如果引发异常,则mplus
在忽略异常时评估第二个参数.
也就是说,运行时异常通常被认为是不合需要的,所以在走这条路之前我会犹豫不决.如果你确实想这样做(并且不介意增加程序在运行时崩溃的可能性),你会找到实现上述内容所需的一切Control.Exception
.
在实践中,我可能要么使用monad变换器方法,如果我想要guard
评估monadic表达式的结果,或者大多数条件依赖于作为函数参数提供的纯值(示例中的标志是)使用@ Anthony的答案中的模式守卫.
我和守卫一起做这件事.
handleFlags :: [Flag] -> IO ()
handleFlags flags
| Help `elem` flags = putStrLn "Usage: program_name options..."
| otherwise = return ()
Run Code Online (Sandbox Code Playgroud)