concrete functor and monad transformers
#89Offer stricter versions of AccumT
AccumT is extremely lazy, much like lazy StateT. I suspect that for most purposes, what users actually want is a version that's strict in the accumulator value. That would correspond to instances (at least approximately) like the following:
instance (Monoid w, Functor m, Monad m) => Applicative (AccumT w m) where
pure a = AccumT $ \ !_ -> return (a, mempty)
{-# INLINE pure #-}
mf <*> mv = AccumT $ \ !w -> do
(f, !w') <- runAccumT mf w
(v, !w'') <- runAccumT mv (w `mappend` w')
return (f v, w' `mappend` w'')
{-# INLINE (<*>) #-}
instance (Monoid w, Functor m, Monad m) => Monad (AccumT w m) where
m >>= k = AccumT $ \ !w -> do
(a, !w') <- runAccumT m w
(b, !w'') <- runAccumT (k a) (w `mappend` w')
return (b, w' `mappend` w'')
{-# INLINE (>>=) #-}
I think it's also plausible that some users will want a version that's strict in the result pairs, but not in the accumulators. Would you be open to offering the totally strict version, and perhaps the pair-strict version?
- description updated
The strict
StateTis only strict in the pairs, which allows users to be strict in the state by usingput $! sormodify'. It can be a bit messy, but it provides the minimal hook to allow users to control strictness of the state. It would make sense to do something similar forAccumT, basically removing all the tildes from the pair matches as strictStateTdoes.That would also make the CPS version of
WriterTredundant.I don't really think the situation is analogous to
StateT. It affects every bind, whereas forStateTmaking state modifications strict can be handled only atputs and with a strictmodify'.You're right: strictness in the pairs isn't much use on its own and strictness in the accumulator is the way to go. We should probably be forcing the
mappends as well.