Proposal: add two more Applicative and Monad adapters

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Proposal: add two more Applicative and Monad adapters

David Feuer
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 <*.

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: add two more Applicative and Monad adapters

David Feuer
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 <[hidden email]> 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 <*.

_______________________________________________
Libraries mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries