I don't know if this makes sense, but it should work at least for Of and (,). The constraints on f look scary, but they really boil down to f being a bifunctor that's a comonad in its second argument.
unzip :: (Monad m, Bifunctor f, Functor (f b), Comonad (f (a,b)))
=> Stream (f (a,b)) m r -> Stream (f a) (Stream (f b) m) r
unzip = loop where
loop str = case str of
Return r -> Return r
Effect m -> Effect (liftM loop (lift m))
Step f -> Step
. first fst
. extend (Effect . Step . first snd)
. fmap (Return . loop) $ f
I don't know if the extra laziness here will cause any performance problems. If it does, and if this idea is actually good for something, we can offer both versions. As with copy, we really only need the power of Extend, not of Comonad.
I don't know if this makes sense, but it should work at least for
Ofand(,). The constraints onflook scary, but they really boil down tofbeing a bifunctor that's a comonad in its second argument.I don't know if the extra laziness here will cause any performance problems. If it does, and if this idea is actually good for something, we can offer both versions. As with
copy, we really only need the power ofExtend, not ofComonad.