On Sat, Jul 17, 2021 at 5:32 AM Carter Schonwald <carter.schonwald@gmail.com> wrote:
What about having the class head be 

Monad m, Functor f=> … MonadFree f m .. 
?
 
Requiring f to be a Functor would be too strong. Plenty of these are not.
 
Is the motivation here to have a more performant liftF?

What are some examples of more efficient implementations for current instances and what’s the performance delta? 

Often the difference can be a walk of the entire structure. I'm not allergic to the idea of just adding the method to the class as proposed, it already has a superclass, so it is already a record internally, etc. 

 
On Fri, Jul 16, 2021 at 6:53 PM David Feuer <david.feuer@gmail.com> wrote:
Another flavor would be to leave liftF alone and add a method that does the same thing with a different name. This would preserve performance characteristics for instances like FT, for situations where the current implementation is faster.

On Fri, Jul 16, 2021, 4:55 PM David Feuer <david.feuer@gmail.com> wrote:
We have

class Monad m => MonadFree f m | m -> f where
  wrap :: f (m a) -> m a

liftF :: (Functor f, MonadFree f m) => f a -> m a
liftF = wrap . fmap pure

I propose we change this to

class Monad m => MonadFree f m | m -> f where
  wrap :: f (m a) -> m a

  liftF :: f a -> m a
  default liftF :: Functor f => f a -> m a
  liftF = wrap . fmap pure

and add a function

defaultWrap :: MonadFree f m => f (m a) -> m a
defaultWrap = join . liftF

This change is not strictly backwards compatible. Some instances might, hypothetically, have to add a Functor constraint. For example, the classic Control.Monad.Free and Control.Monad.Trans.Free would need them. However, those instances already have (currently redundant) Functor constraints, so that doesn't seem like a big deal.

An alternative would be to hew more strictly to backwards compatibility by placing a Functor f constraint on liftF. This seems a bit sad for "freer" instances that don't need it. For example, we have

newtype FT f m a = FT
  { runFT :: forall r. (a -> m r) -> (forall x. (x -> m r) -> f x -> m r) -> m r }

for which

liftF :: f a -> FT f m a
liftF fa = FT $ \pur bndf -> bndf pur fa

_______________________________________________
Libraries mailing list
Libraries@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
_______________________________________________
Libraries mailing list
Libraries@haskell.org
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries