
Andrew Coppin
Currently we have
class Functor c where fmap :: (x -> y) -> (c x -> c y)
This relies on c having kind * -> *. For example, Bytestring cannot be an instance of Functor.
A cleaner solution would be to have something like
class Container c where type Element c :: *
Yes, and I already have ideas and plan to write a library containing such a class (not sure whether I'll stick to ATs or MPTCs+fundeps though).
I then attempted to write
class Container c => Functor c where fmap :: (Functor cx, Functor cy, Element cx ~ x, Element cy ~ y) => (x -> y) -> (cx -> cy)
However, this fails horribly: The type signature fails to mention c. And even if it did, this type signature still isn't correct: It says that fmap can transform *any* functor into *any* other functor, which is wrong.
ListLike does this, and I agree that it's a problem.
It seems that we have gained the ability to talk about containers holding any type of value (even hard-coded types or types with class constraints), but lost the ability to refer to a particular "type of" functor without also specifying the element type.
Does anybody know a straightforward way to fix this? Or is this just a dead end?
I've worked out a way around doing this in the current state of the experimental replacement for fgl: define a new class that tries to force the parametrism back into the non-parametric structure. However, since super-class constraints are currently not available the resulting type sigs are very, very ugly: ,---- | class (InductiveGraph (g n e)) => MappableGraph g n e where | | gmap :: (InductiveGraph (g n' e')) => (Context (g n e) -> Context (g n' e')) | -> g n e -> g n' e' | gmap f = fromContexts . map f . toContexts | | nmap :: ( InductiveGraph (g n' e) | , Node (g n e) ~ Node (g n' e) | , EdgeLabel (g n e) ~ EdgeLabel (g n' e)) | => (NodeLabel (g n e) -> NodeLabel (g n' e)) | -> g n e -> g n' e | nmap f = gmap f' | where | f' (Context ei n l eo) = Context ei n (f l) eo | | emap :: ( InductiveGraph (g n e') | , Node (g n e) ~ Node (g n e') | , NodeLabel (g n e) ~ NodeLabel (g n e')) | => (EdgeLabel (g n e) -> EdgeLabel (g n e')) | -> g n e -> g n e' | emap f = gmap f' | where | f' (Context ei n l eo) = Context (applyF ei) n l (applyF eo) | applyF = map (second f) `---- -- Ivan Lazar Miljenovic Ivan.Miljenovic@gmail.com IvanMiljenovic.wordpress.com