[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
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 at gmail.com
IvanMiljenovic.wordpress.com


More information about the Haskell-Cafe mailing list