Re: Proposal: make liftF a method of MonadFree

David Feuer <[email protected]> Fri, 16 Jul 2021 18:52:24 -0400
Newsgroups gmane.comp.lang.haskell.libraries
Message-ID <CAMgWh9tt6wHxh1+09aSN-f8y7ZH_useoPc1k9R8t8S5+dt9upA@mail.gmail.com>
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 <[email protected]> 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
>
> Pull request at https://github.com/ekmett/free/pull/208
>

_______________________________________________
Libraries mailing list
[email protected]
http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries