在我的程序中,我使用在其中一个模块中定义的函数if'
而不是内置的if-then-else
构造。它的定义很简单,效果很好。
但是,代码中有一个地方需要将其应用于monad值(在我的情况下为IO
),即类型签名应该看起来有点像IO Bool -> IO a -> IO a -> IO a
。
当然,我试图解除它。
if' <$> mb <*> action1 <*> action2
但是当我尝试评估表达时,我得不到我期望的结果。
*Main> if' <$> return True <*> putStrLn "yes" <*> putStrLn "no"
yes
no
我知道<*>
描述读取“顺序应用”,所以也许就是这样。但是这里发生了什么?我可以在不编写全新专用功能的情况下修复它吗?
答案 0 :(得分:3)
(<*>)
评估它的两个参数,因此它有效地解决了一些应用程序的应用程序。检查值和更改计算未来的能力是Monad
类超过Applicative
的额外功率,因此您需要使用它,例如。
mif' :: Monad m => m Bool -> m a -> m a -> m a
mif' bm xm ym = bm >>= (\b -> if b then xm else ym)