如何解除使用a - > IO Bool

时间:2012-01-15 02:53:57

标签: haskell monads

我基本上在寻找find的{​​{1}}类似物:

filterM

但我无法使用findM :: (a -> m Bool) -> [a] -> m (Maybe a) 和某种提升功能自行编写。我目前正在通过find

进行此操作
Data.Maybe.listToMaybe

有效,但似乎我应该能够直接使用x <- filterM f list return $ listToMaybe x

编辑:在hackage上找到一些东西:Control.Monad.Loops.firstMControl.Monad.TM.findM都做我想要的事情

2 个答案:

答案 0 :(得分:1)

好吧,你可以像“

”一样从头开始写
findM p ls =
    case ls of
         []   -> return Nothing
         x:xs -> do
            ok <- p x
            if ok
               then return (Just x)
               else findM p xs

虽然我意识到这比你要求的要优雅得多。我无法弄清楚如何使用某种提升功能来做到这一点。我觉得提升必须在find的递归步骤中发生,它隐藏在函数内部并且无法被提升。虽然我很乐意看到有人证明我错了。

答案 1 :(得分:1)

这是一个无聊,直接的实施:

findM :: Monad m => (a -> m Bool) -> [a] -> m (Maybe a)
findM _ []     = return Nothing
findM f (x:xs) = do
    found <- f x
    if found
        then return $ Just x
        else findM f xs

请注意,此findM不会将f应用于找到的项目之后的任何项目。因此,它在语义上与您发布的filterM实现不同。

您无法在不遗漏的情况下根据find撰写此内容。您已有纯列表,但谓词(a -> m Bool)(a -> Bool)所需的find不符。如果您使用mapM将谓词应用于每个项目,则只需[Bool],您需要将其压缩到原始列表中。