[Haskell-cafe] More experiments with ATs
Ivan Lazar Miljenovic
ivan.miljenovic at gmail.com
Sat Jul 3 10:44:52 EDT 2010
Andrew Coppin <andrewcoppin at btinternet.com> writes:
> 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
> 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'
| 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'
| f' (Context ei n l eo) = Context (applyF ei) n l (applyF eo)
| applyF = map (second f)
Ivan Lazar Miljenovic
Ivan.Miljenovic at gmail.com
More information about the Haskell-Cafe