Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Map natural transformation for FreeT #5

Closed
Gabriella439 opened this issue Sep 7, 2012 · 4 comments
Closed

Map natural transformation for FreeT #5

Gabriella439 opened this issue Sep 7, 2012 · 4 comments

Comments

@Gabriella439
Copy link
Contributor

Would you be interested in adding the following function to FreeT:

mapFreeT :: (Functor f, Monad m) => (forall x . m x -> n x) -> FreeT f m r -> FreeT f n r
mapFreeT nat = FreeT . nat . liftM (fmap (mapFreeT nat)) . runFreeT

This greatly resembles an IFunctor instance, except for the (Monad m) (or (Functor m)) constraint. In the longer run, when working on your indexed package you might consider N versions of all the indexed classes (i.e. NFunctor, NMonad) that have functor constraints on the last type variable that are appropriate for the world of natural transformations.

This kind of transformation is generally useful for all monad transformers since it allows you to change the base monad for a pre-existing function. For example, if I write a pipe like:

fileReader :: Producer ByteString IO ()

... and let's say I have another pipe that folds its input:

someFold :: (Monad m) => Pipe a b (WriterT m) r

I could make them compatible just by writing:

pipe :: someFold <+< mapFreeT lift fileReader

This isn't a blocking issue for me switching to free for pipes, and I plan on switching soon regardless. This is more of a "nice to have" thing. Also, it doesn't have to be a named function. If you find an appropriate class for it you can use that, too.

@ekmett
Copy link
Owner

ekmett commented Sep 7, 2012

I'm not actively against adding this. =)

Let me check the extensions used, and if it doesn't extend the set then it'll definitely go in.

@Gabriella439
Copy link
Contributor Author

Like I said, it's not a blocking issue. If worse comes to worse I'll
just include it as a utility function in pipes.

On 09/07/2012 02:31 PM, Edward A. Kmett wrote:

I'm not actively against adding this. =)

Let me check the extensions used, and if it doesn't extend the set
then it'll definitely go in.


Reply to this email directly or view it on GitHub
#5 (comment).

@Gabriella439
Copy link
Contributor Author

Oh, I just realized that if the Rank2Types extension is a problem you can copy what Ross does for transformers. Instead of providing a natural transformation he specializes the first argument to the concrete function that the compiler infers:

mapFreeT
  :: (Monad m, Functor f)
  => (m (FreeF f a (FreeT g n b)) -> n (FreeF g b (FreeT g n b)))
  -> FreeT f m a -> FreeT g n b

This still works correctly for monad morphisms, at the expense of an uglier type signature that hides the purpose of the function. However, you could add a documentation note saying something like:

"The typical use is to pass mapFreeT a monad morphism of type forall r . m r -> n r as its first argument so that you get a new monad morphism that modifies the base monad: forall r . FreeT f m r -> FreeT f n r"

@ekmett
Copy link
Owner

ekmett commented Sep 10, 2012

I just decided to add the Rank2Types requirement. This will let me move the Church encoded free monad from kan-extensions to here, which reduces the amount of crap people need to install in order to use it considerably.

@ekmett ekmett closed this as completed Sep 10, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants