Generalize copy, perhaps
I don't actually know if this "makes sense", but it works for Of and (,), and it kind of smells right.
copy :: (Monad m, Comonad f) => Stream f m r -> Stream f (Stream f m) r
copy = Effect . return . loop where
loop str = case str of
Return r -> Return r
Effect m -> Effect (fmap loop (lift m))
Step f -> Effect (Step (extend (Return . Step) (fmap loop f)))
Comonad is actually overkill; we only really need Extend from Data.Functor.Extend in semigroupoids. Unfortunately, that's not a superclass.
I was talking with Cale Gibbard, who said it seemed to go with an extract-like generalization of effects, which is very definitely possible as well, forming some sort of higher-level comonad or something:
effects :: (Monad m, Comonad f) => Stream f m r -> m r
If you only need extend you could also ask that to be passed in as a parameter. Not sure if that permits other "interesting" extends
@ocharles, that's a good idea for avoiding the dependency. It's kind of an ugly parameter, and would require a separate function (rather than replacing copy), but that seems fairly tolerable.
Well, I suggest it more from wondering if as you only want Extend you really do just want to supply that function. Plus, maybe it means something interesting (like traverse being useful when given as a parameter as it's a traversal)
@ocharles, yes, that's a good point too, and the answer is ... yes! We can get
copygen :: (Monad m, Functor f)
=> (forall a b. (f a -> b) -> f a -> g b)
-> Stream f m r -> Stream f (Stream g m) r
Actually, we can even get
copygen :: (Monad m, Functor g)
=> (forall a b. (f a -> b) -> g a -> h b)
-> Stream g m r -> Stream f (Stream h m) r
This is no longer the official repo for streaming. Please continue discussion of this issue here.