提升的“如果”函数表现出意外

Lifted „if“-function behaves unexpectedly

在我的程序中,我使用了在其中一个模块中定义的函数 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

我知道 <*> 描述是“顺序应用”,所以也许就是这样。但是这里发生了什么?我可以在不编写全新的专用函数的情况下修复它吗?

(<*>) 评估它的两个参数,因此它有效地提升了一些应用程序的应用程序管道。检查值和改变计算的未来的能力是 Monad class 超过 Applicative 的额外能力,所以你需要使用它来代替,例如

mif' :: Monad m => m Bool -> m a -> m a -> m a
mif' bm xm ym = bm >>= (\b -> if b then xm else ym)