Also worth considering: manyM :: (Alternative f, Monad f) => f a -> f [a] manyM v = many_v where many_v = do ma <- optional v case ma of Nothing -> pure [] Just a -> liftA2 (:) a many_v someM :: (Alternative f, Monad f) => f a -> f [a] someM v = liftA2 (:) v (manyM v) Unlike the default definitions, these bound backtracking when (<|>) represents that. On Sat, Aug 11, 2018, 1:19 PM David Feuer <david.feuer@gmail.com> wrote:
We currently offer liftA, liftM, liftM2, and ap to implement Functor and Applicative methods in terms of Applicative and Monad ones. But there are a couple other functions in that general vein that are missing. I propose that we should add at least replaceA, and perhaps also beforeM.
-- (<$) = replaceA -- This may be better than the default if there is -- an optimized definition of *> (which may be -- based on an optimized >>). replaceA :: Applicative f => a -> f x -> f a replaceA a fa = fa *> pure a
-- (<*) = beforeM -- This may be better than the default if there is -- an optimized definition of <$, or if <$ is defined as -- replaceA and *> is optimized. beforeM :: Monad f => f a -> f x -> f a beforeM fa fx = fa >>= \a -> a <$ fx
Why a <$ fx and not fx >> pure a? Because <$ could be implemented specially, and is unlikely to be implemented by hand using <* if there isn't a custom <*.