我发现很多东西我自己一起跳起来似乎完全有用,实际上有一个我不知道的标准实现,所以很奇怪,如果有人能说他们已经看到了这个之前使用的东西类型:
它需要一个monadic函数并将折叠它,直到通过替代选择谓词然后它返回谓词的结果:
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
我意识到这个名字是一个前奏冲突,我可能会把它命名为别的,但我想我首先要看看在标准库中是否已经有类似的功能我只是#39; t know about ..
此外,我想我很好奇我写的组成替代方案是在其他地方定义的,还是这些功能中的任何一个看起来都是错误的。但问题的关键在于,这是在其他地方实施的,还是在其他地方实施的非常相似的事情
答案 0 :(得分: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
在Control.Monad.Loops中有一个名为untilM
的类似函数,它使用Bool
谓词,LoopT
转换器可用于Control.Monad.Trans.Loop中的任意循环。但不,这个特殊的功能似乎并不出名。