Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add MonadAccum #89

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Unreleased
* Remove `Control.Monad.List` and `Control.Monad.Error`
* Remove instances of deprecated `ListT` and `ErrorT`
* Add instances for `Control.Monad.Trans.Accum` and `Control.Monad.Trans.Select`
* Add `MonadAccum` and corresponding instances

2.2.2
-----
Expand Down
30 changes: 30 additions & 0 deletions Control/Monad/Accum.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{-# LANGUAGE CPP #-}
-----------------------------------------------------------------------------
-- |
-- Module : Control.Monad.Accum
-- Copyright : (c) Manuel Bärenz,
-- License : BSD-style (see the file LICENSE)
--
-- Maintainer : libraries@haskell.org
-- Stability : experimental
-- Portability : non-portable (multi-param classes, functional dependencies)
--
-- The MonadAccum class.
--
-- Inspired by the paper
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should remove this section given this transformer is not inspired by that paper. Some similar modules don't have this disclaimer in them, such as Control.Monad.Identity.

-- /Functional Programming with Overloading and Higher-Order Polymorphism/,
-- Mark P Jones (<http://web.cecs.pdx.edu/~mpj/pubs/springschool.html>)
-- Advanced School of Functional Programming, 1995.
-----------------------------------------------------------------------------

module Control.Monad.Accum (
Copy link
Member

@chessai chessai Sep 3, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of re-exporting the modules, we need the haddocks to look like others. In order to do that, we need three sections:

  • MonadAccum class
  • The Accum monad
  • The AccumT monad transformer

Please refer to eg the documentation for Control.Monad.Reader

module Control.Monad.Accum.Class,
#if MIN_VERSION_transformers(0,5,3)
module Control.Monad.Trans.Accum,
#endif
) where

#if MIN_VERSION_transformers(0,5,3)
import Control.Monad.Trans.Accum (AccumT (..), runAccum, runAccumT, execAccum, execAccumT, evalAccum, evalAccumT, mapAccum, mapAccumT)
#endif
import Control.Monad.Accum.Class
174 changes: 174 additions & 0 deletions Control/Monad/Accum/Class.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE TupleSections #-}
-----------------------------------------------------------------------------
-- |
-- Module : Control.Monad.Accum.Class
-- Copyright : (c) Manuel Bärenz,
-- License : BSD-style (see the file LICENSE)
--
-- Maintainer : libraries@haskell.org
-- Stability : experimental
-- Portability : non-portable (multi-param classes, functional dependencies)
--
-- The MonadAccum class.
--
-- Inspired by the paper
-- /Functional Programming with Overloading and Higher-Order Polymorphism/,
-- Mark P Jones (<http://web.cecs.pdx.edu/~mpj/pubs/springschool.html>)
-- Advanced School of Functional Programming, 1995.
-----------------------------------------------------------------------------

module Control.Monad.Accum.Class (
MonadAccum(..),
looks,
) where

import Control.Monad.Trans.Except as Except
import Control.Monad.Trans.Identity as Identity
import Control.Monad.Trans.Maybe as Maybe
import Control.Monad.Trans.Reader
import qualified Control.Monad.Trans.RWS.Lazy as Lazy (
RWST, writer, tell, listen, pass)
import qualified Control.Monad.Trans.RWS.Strict as Strict (
RWST, writer, tell, listen, pass)
import Control.Monad.Trans.State.Lazy as Lazy
import Control.Monad.Trans.State.Strict as Strict
import qualified Control.Monad.Trans.Writer.Lazy as Lazy (
WriterT, writer, tell, listen, pass)
import qualified Control.Monad.Trans.Writer.Strict as Strict (
WriterT, writer, tell, listen, pass)

#if MIN_VERSION_transformers(0,5,3)
import qualified Control.Monad.Trans.Accum as Accum
#endif

#if MIN_VERSION_transformers(0,5,6)
import qualified Control.Monad.Trans.RWS.CPS as CPS (
RWST, writer, tell, listen, pass)
import qualified Control.Monad.Trans.Writer.CPS as CPS (
WriterT, writer, tell, listen, pass)
#endif

import Control.Monad.Trans.Class (lift)
import Control.Monad
import Data.Monoid

class (Monoid w, Monad m) => MonadAccum w m | m -> w where
#if __GLASGOW_HASKELL__ >= 707
{-# MINIMAL (accum | look, add) #-}
#endif
-- | 'accum' embeds an accumulation action.
accum :: (w -> (a, w)) -> m a
accum f = do
w <- look
let ~(a, w') = f w
add w'
return a

-- | @'add' w@ is an action that adds @w@ to the log.
add :: w -> m ()
add w = accum $ const ((),w)

-- | 'look' returns the log accumulated so far.
look :: m w
look = accum (, mempty)

-- | @'looks' f@ returns 'f' applied to the log accumulated so far.
--
-- * @'looks' f = f <$> 'look'@
looks :: MonadAccum w m => (w -> a) -> m a
looks f = f <$> look

#if MIN_VERSION_transformers(0,5,3)
instance (Monoid w, Monad m) => MonadAccum w (Accum.AccumT w m) where
accum = Accum.accum
add = Accum.add
look = Accum.look
#endif

-- ---------------------------------------------------------------------------
-- Instances for other mtl transformers
--
-- All of these instances need UndecidableInstances,
-- because they do not satisfy the coverage condition.

-- | @since 2.3
instance MonadAccum w m => MonadAccum w (ExceptT e m) where
accum = lift . accum
add = lift . add
look = lift look

-- | @since 2.3
instance MonadAccum w m => MonadAccum w (IdentityT m) where
accum = lift . accum
add = lift . add
look = lift look

-- | @since 2.3
instance MonadAccum w m => MonadAccum w (MaybeT m) where
accum = lift . accum
add = lift . add
look = lift look

-- | @since 2.3
instance MonadAccum w m => MonadAccum w (ReaderT r m) where
accum = lift . accum
add = lift . add
look = lift look

-- | @since 2.3
instance MonadAccum w m => MonadAccum w (Lazy.StateT s m) where
accum = lift . accum
add = lift . add
look = lift look

-- | @since 2.3
instance MonadAccum w m => MonadAccum w (Strict.StateT s m) where
accum = lift . accum
add = lift . add
look = lift look

#if MIN_VERSION_transformers(0,5,6)
-- | @since 2.3
instance MonadAccum w m => MonadAccum w (CPS.WriterT w m) where
accum = lift . accum
add = lift . add
look = lift look
#endif

-- | @since 2.3
instance MonadAccum w m => MonadAccum w (Lazy.WriterT w m) where
accum = lift . accum
add = lift . add
look = lift look

-- | @since 2.3
instance MonadAccum w m => MonadAccum w (Strict.WriterT w m) where
accum = lift . accum
add = lift . add
look = lift look


#if MIN_VERSION_transformers(0,5,6)
-- | @since 2.3
instance MonadAccum w m => MonadAccum w (CPS.RWST r w s m) where
accum = lift . accum
add = lift . add
look = lift look
#endif

-- | @since 2.3
instance MonadAccum w m => MonadAccum w (Lazy.RWST r w s m) where
accum = lift . accum
add = lift . add
look = lift look

-- | @since 2.3
instance MonadAccum w m => MonadAccum w (Strict.RWST r w s m) where
accum = lift . accum
add = lift . add
look = lift look
2 changes: 2 additions & 0 deletions mtl.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ source-repository head

Library
exposed-modules:
Control.Monad.Accum
Control.Monad.Accum.Class
Control.Monad.Cont
Control.Monad.Cont.Class
Control.Monad.Error.Class
Expand Down