Haskell-MMorph-Library
Haskell-MMorph-Library copied to clipboard
Deriving MFunctor
As far as I can see MFunctor
can be derived in a similar way as Functor
is derived.
I don't have enough TH background yet, so it might take some time if no one would like to make it :)
I didn't even know that was possible. However, I would prefer this in a separate package (i.e. mfunctor-derive
) so that mmorph
stays really low on dependencies. Keep in mind that conduit
is the major consumer of mmorph
and an unexpected dependency on template-haskell
might cause problems for conduit
.
Also, should I go ahead and upload the generalize
code to Hackage, or do you want me to wait for this issue to be resolved first?
This would take a lot of time and indeed in a separate package. So I would prefer generalize
on Hackage first :)
Okay. Just give me a second because I was going through my e-mail and I saw another suggestion for mmorph
, which I just created as issue #4. I may want to spend a day or two thinking about that first.
I believe deriving could be implemented similar to this: http://www.mail-archive.com/[email protected]/msg02116.html (also see derive
package on hackage, specifically Data.Derive.Functor
).
I don't have enough time to learn TH right now, so feel free to implement the idea. As Gabriel noticed this should probably implemented within a separate package, say, mmorph-derive
or mfunctor-derive
.
Some related stuff:
data T m a = C1 u v w | C2 x y z | ...
instance MFunctor T where
hoist f t = case t of
C1 q r s -> C1 (hoist_<a,u> f q) (hoist_<a,v> f r) (hoist_<a,w> f s)
C2 t u v -> C1 (hoist_<a,x> f t) (hoist_<a,y> f u) (hoist_<a,z> f v)
...
-- where
hoist_<m, x> f = id
hoist_<m, m x> f = f . fmap (hoist_<m,x> f)
hoist_<m, T x> f = fmap (hoist_<a,x> f)
hoist_<m, T x y> f = fmap2 (hoist_<a,x> f) . fmap (hoist_<a,y> f)
-- etc.
hoist_<m, x -> y> f = \u -> hoist_<m,y> f . u . contrahoist_<m,x> f
contrahoist_<m, x> f = id
contrahoist_<m, T x> f = cofmap (hoist_<m,x> f)
contrahoist_<m, T x y> f = cofmap2 (hoist_<m,x> f) . cofmap (hoist_<m,y> f)
-- etc.
contrahoist_<m, x -> y> f = \u -> contrahoist_<m,y> f . u . hoist_<m,x> f
An example of derivation:
data StateT s m a = StateT (s -> m (a, s))
instance MFunctor (StateT s) where
hoist f (StateT g) = StateT (hoist_<m,s -> m (a,s)> f g)
= StateT (hoist_<m,m (a,s)> f . g . contrahoist_<m,s> f)
= StateT (f . fmap (hoist_<m,(a,s)> f) . g . id)
= StateT (f . fmap id . g . id)
= StateT (f . g)