Why can't I generalize this from the Monad to the Application?

I generalized hoistFreefrom free package to hoistFreeM, similar to how you can generalize fmapto Data.Traversable.mapM.

import Control.Monad
import Control.Monad.Free
import Data.Traversable as T

hoistFreeM :: (Traversable g, Monad m) =>
              (forall a. f a -> m (g a)) -> Free f b -> m (Free g b)
hoistFreeM f = go
  where go (Pure x)  = return $ Pure x
        go (Free xs) = liftM Free $ T.mapM go =<< f xs

However, I do not think that there is a way to further generalize it to work with anyone Applicative, similar to how you can generalize Data.Traversable.mapMto Data.Traversable.traverse. I'm right? If so, why?

+4
source share
1 answer

Free Monad, Monad ( (>>=) join), Applicative . , , ,

-- also from the `free` package
data Ap f a where
  Pure :: a -> Ap f a
  Ap :: f a -> Ap f (a -> b) -> Ap f b

hoistAp :: (forall a. f a -> g a) -> Ap f b -> Ap g b
hoistAp _ (Pure a) = Pure a
hoistAp f (Ap x y) = Ap (f x) (hoistAp f y)

hoistApA :: Applicative v => (forall a. f a -> v (g a)) -> Ap f b -> v (Ap g b)
hoistApA _ (Pure a) = pure (Pure a)
hoistApA f (Ap x y) = Ap <$> f x <*> hoistApA f y

-- just what you'd expect, really

, hoistFreeM hoistFreeA.

hoistFreeA :: (Traversable f, Applicative v) =>
              (forall a. f a -> v (g a)) -> Free f b -> v (Free g b)
hoistFreeA _ (Pure a) = pure (Pure a)

hoistFreeM . mapM traverse,

hoistFreeA f (Free xs) = ?f $ traverse (hoistFreeA f) xs

?f , , . ,

?f :: v (f (Free g b)) -> v (Free g b)

, f g, v. v, v Functor, f a g a forall a . f a -> v (g a).

f Free, g .

hoistFreeA f (Free xs) = ?f . fmap (fmap Free . f) $ traverse (hoistFreeA f) xs

?f :: v (v (Free g b)) -> v (Free g b)

join, . , . Monads Monad , , , - join bind.

+7

All Articles