haskellari / these

An either-or-both data type, with corresponding hybrid error/writer monad transformer.
117 stars 49 forks source link

CPS version of ChronicleT #173

Open pkamenarsky opened 2 years ago

pkamenarsky commented 2 years ago

Would it make sense to add a CPS version of ChronicleT, similar to Control.Monad.Trans.Writer.CPS, in order to achieve constant space usage?

phadej commented 2 years ago

What that version would look like? Note that Chronicle is closer to Either / ExceptT, and CPS variants of these are not in transformers / mtl. They could, there are some versions in e.g. unification-fd

newtype EitherKT e m a = EKT (forall r. (a -> m (Either e r)) -> m (Either e r))

and there could be one more often used in parsers

newtype EitherCpsT e m a = ECT (forall r. (a -> m r) -> (e -> m r) -> m r)

but i'd prefer seeing this in transformers / mtl first to then follow their overall style, module naming, type naming scheme, etc.

pkamenarsky commented 2 years ago

I was thinking about something like:

newtype ChronicleT c m a = ChronicleT { runChronicleT :: c -> m (These c a) }

So that dictate (the equivalent of tell) doesn't accumulate mappend thunks:

dictate :: (Semigroup c, Monad m) => c -> ChronicleT c m ()
dictate c' = ChronicleT $ \c -> let ct = c `mappend` c' in ct `seq` pure (These ct ())
phadej commented 2 years ago

I see. Ok, I'll be happy to review a PR adding that in .CPS module.