6

我发现很多我自己拼凑起来的东西似乎很有用,实际上有一个我不知道的标准实现,所以很好奇是否有人可以说他们以前见过这种类型的东西:

它接受一个单子函数并将其折叠,直到一个谓词被替代选择,然后它返回谓词的结果:

until :: (Monad m, Alternative m) => (a -> m a) -> (a -> m c) -> a -> m c
f `until` p = \a -> (f >=> (p `altF` (until f p))) a
  where f1 `altF` f2 = \a -> f1 a <|> f2 a

我意识到这个名字是一个前奏冲突,我可能会用别的名字来命名它,但我想我会先看看在我不知道的标准库中是否已经有类似的功能......

此外,我想我很好奇我写的组合替代方案是否在其他地方定义,或者这些功能中的任何一个似乎一开始就被误导了。但我的问题的症结是,这是在其他地方实现的,还是在其他地方实现的非常相似的东西

4

1 回答 1

7

有大量的便利函数不在 Prelude 或标准库中,但也许应该在。如果您发现它们有用,我不会为重新实现一些而烦恼太多。

请注意,这altF相当于liftA2 (<|>),您可能会这样写:

till :: (Monad m, Alternative m) => (a -> m a) -> (a -> m b) -> a -> m b

-- To do f till p is to first do f; then either p, or f till p.
f `till` p = f >=> (<|>) <$> p <*> f `till` p

请注意,这(Monad m, Alternative m)与 非常相似MonadPlus m,您可以稍微简化一下类型:

till :: MonadPlus m => (a -> m a) -> (a -> m b) -> a -> m b
f `till` p = f >=> mplus <$> p <*> f `till` p

untilMControl.Monad.Loops中调用了一个类似的函数,它使用Bool谓词,并且在Control.Monad.Trans.LoopLoopT中存在一个用于任意循环的转换器。但是不,这个特殊的功能似乎还没有出名。

于 2013-03-06T09:11:29.287 回答