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

Add copy operations #164

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

Add copy operations #164

wants to merge 2 commits into from

Conversation

treeowl
Copy link

@treeowl treeowl commented Sep 8, 2017

These are the FreeT editions of a generalization of streaming:Streaming.Prelude.copy.

copy :: (Applicative m, Comonad f) => FreeT f m r -> FreeT f (FreeT f m) r
copy' :: (Applicative m, Extend f) => FreeT f m r -> FreeT f (FreeT f m) r

Cale Gibbard suspects copy might make some sensible comonadish thing along with

extrude :: (Monad m, Comonad f) => FreeT f m r -> m r
extrude = iterT extract

These are the `FreeT` editions of a generalization of
`streaming:Streaming.Prelude.copy`.

```haskell
copy :: (Applicative m, Comonad f) => FreeT f m r -> FreeT f (FreeT f m) r
copy' :: (Applicative m, Extend f) => FreeT f m r -> FreeT f (FreeT f m) r
```

Cale Gibbard suspects `copy` might make some sensible comonadish thing
along with

```haskell
extrude :: (Monad m, Comonad f) => FreeT f m r -> m r
extrude = iterT extract
```
@treeowl
Copy link
Author

treeowl commented Sep 8, 2017

We can also take extend as an argument, as @ocharles suggested for the streaming version I proposed:

copygen :: (Applicative m, Functor f)
        => (forall a b. (f a -> b) -> f a -> g b)
        -> FreeT f m r -> FreeT f (FreeT g m) r
copygen g (FreeT t) = FreeT $ FreeT $ flip fmap t $
  \str -> case str of
    Pure r -> Pure (Pure r)
    Free f -> Free $ g (FreeT . pure . Pure . Free) (fmap (copygen g) f)

Note that this version allows the caller to change the inner functor.

@treeowl
Copy link
Author

treeowl commented Sep 8, 2017

Even better:

copygen :: (Applicative m, Functor g)
        => (forall a b. (f a -> b) -> g a -> h b)
        -> FreeT g m r -> FreeT f (FreeT h m) r
copygen g (FreeT t) = FreeT $ FreeT $ flip fmap t $
  \str -> case str of
    Pure r -> Pure (Pure r)
    Free f -> Free $ g (FreeT . pure . Pure . Free) (fmap (copygen g) f)

@treeowl
Copy link
Author

treeowl commented Sep 17, 2017

The Applicative constraint is a bit annoying. The presence of <*>, which we don't even use, greatly weakens the explanatory power of the type signature. I believe that if we could reasonably use Pointed instead, then the behavior would be fully determined. It would at least be obvious that no effects are duplicated. I wonder if there's a nice way to avoid that.

@treeowl
Copy link
Author

treeowl commented Sep 18, 2017

Aha! I may have found part of a way. If we write

expound :: (Functor m, Functor g)
        => (forall a b. (m (f a) -> b) -> g a -> h b)
        -> FreeT g m r -> FreeT f (FreeT h m) r

which is not hard, then it's possible to define copygen in terms of it with the sole addition of pure. But it has an extra fmap.... I'll keep thinking on it.

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

Successfully merging this pull request may close these issues.

1 participant