Closed turion closed 1 year ago
This is a smaller version of https://github.com/ekmett/free/pull/186.
It's a bit ridiculous to write & debug for 7.* GHCs which I can't even install locally, but well.
I would be in favor of dropping support for pre-8.0 GHCs, given that they are increasingly becoming a barrier to contributors. I have already been dropping pre-8.0 support on other @ekmett libraries whenever this sort of situation arises, and I think it is time to do the same for free
.
Would you be willing to wait until that happens before proceeding with this PR? (Alternatively, you could even submit a PR that drops pre-8.0 support if you'd like, but if you'd prefer, I could also do this myself.)
I would be in favor of dropping support for pre-8.0 GHCs, given that they are increasingly becoming a barrier to contributors. I have already been dropping pre-8.0 support on other @ekmett libraries whenever this sort of situation arises, and I think it is time to do the same for free.
Yes :tada: highly in favour of this.
Would you be willing to wait until that happens before proceeding with this PR?
Yes sure!
(Alternatively, you could even submit a PR that drops pre-8.0 support if you'd like, but if you'd prefer, I could also do this myself.)
I would in principle, but I don't know how to find all the places where there are needless Functor m
constraints. I don't know the codebase as well, so I'd rather leave that part to you.
I don't know the codebase as well, so I'd rather leave that part to you.
That is entirely reasonable—thank you for confirming. As a first pass, I think I will build free
with -Wredundant-constraints
to see which constraints can simply be removed without needing further code changes. After that, I'll hand it over to you.
(Also, my apologies for not noticing #154/#186 previously. I think these came about before I become a co-maintainer of the library, so they slipped under my radar.)
I've submitted #227 to drop support for pre-8.0 GHCs and remove "trivially" redundant constraints (i.e., constraints that are redundant without requiring any further code changes).
To help improve my own understanding, I've collected all of the places in #154, #186, and this PR where the implementation of class methods can be changed to relax superclass constraints:
Relaxing this Monad m
constraint in Control.Monad.Trans.Free
:
To a Functor m
constraint:
instance (Functor f, Functor m) => Functor (FreeT f m) where
fmap f (FreeT m) = FreeT (fmap f' m) where
This is the only implementation change in #154, and the first of three implementation changes in this PR. (As a result, this PR supersedes #154.)
The second implementation change in this PR is to relax this Monad m
constraint in Control.Monad.Trans.Free.Ap
:
To a Functor m
constraint:
instance (Functor f, Functor m) => Functor (FreeT f m) where
fmap f (FreeT m) = FreeT (fmap f' m) where
The third implementation change in this PR is to relax this Monad
constraint in Control.Monad.Trans.Free.Ap
:
To an Applicative m
constraint:
instance (Applicative f, Applicative m) => Applicative (FreeT f m) where
pure a = FreeT (pure (Pure a))
Relaxing this Monad m
constraint in Control.Monad.Trans.Free
:
To an Applicative m
constraint:
instance (Functor f, Functor m, Applicative m) => Applicative (FreeT f m) where
pure a = FreeT (pure (Pure a))
{-# INLINE pure #-}
FreeT mf <*> FreeT mx = FreeT $ liftA2 q mf mx
where
Pure a `q` Pure b = Pure $ a b
Pure a `q` Free b = Free $ fmap a <$> b
Free a `q` b = Free $ (<*> FreeT (pure b)) <$> a
{-# INLINE (<*>) #-}
Relaxing this Monad m
constraint in Control.Monad.Trans.Free.Church
:
To an Applicative m
constraint:
instance (Foldable f, Foldable m, Applicative m) => Foldable (FT f m) where
foldr f r xs = F.foldr (<<<) id inner r
where
inner = runFT xs (pure . f) (\xg xf -> F.foldr (liftA2 (<<<) . xg) (pure id) xf)
{-# INLINE foldr #-}
foldl' f z xs = F.foldl' (!>>>) id inner z
where
(!>>>) h g = \r -> g $! h r
inner = runFT xs (pure . flip f) (\xg xf -> F.foldr (liftA2 (>>>) . xg) (pure id) xf)
{-# INLINE foldl' #-}
Relaxing this Monad m
constraint in Control.Monad.Trans.Iter
:
To a Functor m
constraint:
instance Functor m => Functor (IterT m) where
fmap f = IterT . fmap (bimap f (fmap f)) . runIterT
Monad m
constraint in Control.Monad.Trans.Free
's hoistFreeT
and transFreeT
functions to Functor m
. Similarly for the functions of the same name in Control.Monad.Trans.Free.Ap
.Monad m
constraint in Control.Monad.Trans.Free
's cutoff
function to Applicative m
. Similarly for the function of the same name in Control.Monad.Trans.Free.Ap
.Monad m
constraint in Control.Monad.Trans.Free.Church
's joinFT
function to Applicative m
.There are likely other constraints downstream that can be relaxed as a result of these changes, but the changes above are the primary ones.
I agree with your assessment. I've rebased and pushed.
CI weather isn't good it seems... can we rerun?
Excellent, thanks for being patient! Although CI is being temperamental, the code itself looks great. I'll go ahead and land this.
Some instances for
Functor
andApplicative
for free monad transformers needlessly requireMonad m
for the inner monad. This PR relaxes these constraints toFunctor
andApplicative
, respectively, and makes some trivial code changes.