B计划,或者与Maybe's>> =相反的是什么?

时间:2014-07-23 05:22:59

标签: haskell maybe

让我们采取两个功能:

f :: a -> Maybe b
g :: b -> Maybe c

函数>>=的工作方式是f >>= g只有在g f时才会执行Nothing f。换句话说,它需要gf :: a -> Maybe b g :: a -> Maybe b planb :: (a -> Maybe b) -> (a -> Maybe b) -> (a -> Maybe b) planb f g = \x -> case f x of Nothing -> g x res -> res 才能成功产生任何结果。

我正在实现一个解析器,并意识到我的词法分析器会从中获益。那就是:

f

表示尝试g,如果失败,请尝试planb作为备用计划。使用词法分析器意味着尝试将令牌类型与当前输入匹配,如果失败,请尝试匹配另一个令牌类型(最终将为所有令牌类型链接)。

搜索Hoogle并没有导致任何此类功能,但对我来说这样的功能似乎在许多地方都很有用!

我的问题是,我是否应该使用Monad的变体?如果没有,我会做一些非凡的事情,有更好的方法来实现我想要的目标吗?


P.S。我考虑过这个函数一般对Maybe是否有意义,但对{{1}}之外的其他人来说并没有那么大的意义。

2 个答案:

答案 0 :(得分:20)

Alternative类型类正是这样做的,它与MonadPlus非常相似,但可能更为一般。

import Control.Applicative

-- most general form
planb :: (Applicative g, Alternative f) => g (f a) -> g (f a) -> g (f a)
planb = liftA2 (<|>)

-- specialized to (->) and Maybe
planb' :: (a -> Maybe b) -> (a -> Maybe b) -> (a -> Maybe b)
planb' = planb

-- equivalent to planb' (and planb) but without the fancy combinators
planb'' :: (a -> Maybe b) -> (a -> Maybe b) -> a -> Maybe b
planb'' f g x = f x <|> g x

将其插入一个简单的测试用例:

test :: Maybe Int
test = do
  a <- planb' (const Nothing) id (Just 1)
  b <- planb' id id (Just 1)
  c <- planb' id (const Nothing) (Just 1)
  return $ a + b + c

生成预期结果:

*Main> test
Just 3

答案 1 :(得分:6)

请注意,您的planb功能实际上只需要对Maybe值进行操作;调用函数来生成它们可以被考虑在内。

planb :: Maybe a -> Maybe a -> Maybe a
planb Nothing b = b
planb a _ = a

您可以将其称为planb (f x) (g x),以获得Maybe结果。

考虑到这一点,请查看MonadPlus class(在评论中Franky建议):

planb = mplus

您可能还对msum感兴趣,Maybe会获取Nothing值列表并返回不是matchSomehow :: [a -> Maybe b] -> a -> Maybe b matchSomehow fs a = msum $ map ($a) fs 的第一个值(如果有)。这是一个方便的功能:

{{1}}