the MPTC Dilemma (please solve)

Roman Leshchinskiy rl at cse.unsw.EDU.AU
Thu Mar 23 08:28:02 EST 2006


On Thu, 23 Mar 2006, Claus Reinke wrote:

>>>               class Graph (g e v) where
>>>                   src :: e -> g e v -> v
>>>                   tgt :: e -> g e v -> v
>>> 
>>>               we associate edge and node types with a graph type by
>>>               making them parameters, and extract them by matching.
>> 
>> If I understand correctly, this requires all graphs to be polymorphic in 
>> the types of edges and vertices. Thus, you cannot (easily) define a graph 
>> which provides, say, only boolean edges. Moreover, doesn't this require 
>> higher-order matching?
>
> I've already answered the last question. as for polymorphism, all this
> requires is for a graph type parameterized by an edge and vertex
> type (just as the SML solution, which got full marks in this category,
> requires instantiations of the edge and vertex types in the graph structure).

Ah, I see. You are suggesting to introduce phantom type parameters to fake 
polymorphism for types which aren't really polymorphic. This might be 
acceptable as a temporary workaround but I don't think it is a good 
long-term solution. The ML implementation is not really comparable to this 
as instantiating structures is quite different from instantiating types.

>>>               class Edge g e | g -> e
>>>               instance Edge (g e v) e
>>>               class Vertex g v | g -> v
>>>               instance Vertex (g e v) v
>>> 
>>>               class (Edge g e,Vertex g v) => Graph g where
>>>                   src :: e -> g -> v
>>>                   tgt :: e -> g -> v
>>> 
>>>               (this assumes scoped type variables; also, current GHC,
>>>                contrary to its documentation, does not permit entirely 
>>> FD-determined variables in superclass contexts)
>> 
>> This does not seem to be a real improvement to me and, in fact, seems quite 
>> counterintuitive.
>
> it is, however, probably as close as we can come within current Haskell,

In what sense is this current Haskell? For this to work, you need at the 
very least to

   a) allow FD-determined variables to appear only in the superclass
      contexts but not in the head of class declarations (not supported by
      GHC at the moment),
   b) rely on scoped type variables (in a way which GHC doesn't support at
      the moment) and
   c) provide a way to keep FD outputs abstract even when the inputs are
      known (not supported by GHC).

While a) and b) might be fairly minor changes to GHC, c) seems to be a 
major one. Even if all this is added, what you end up with is essentially 
a verbose and counterintuitive hack for something which should be easy to 
do. This is not meant as a criticism of your (very interesting, IMO) 
approach - I agree that this is probably the best you can do with FDs. 
It's just that FDs simply seem to be a less than optimal mechanism for 
this kind of programming.

Also, it might be worth pointing out that even if all of the above worked,
you still couldn't do

   data VertexPair g = VP (Vertex g) (Vertex g)
   fstVertex :: Graph g => VertexPair g -> Vertex g
   fstVertex (VP v1 v2) = v1

   type Vertices g = [Vertex g]

Roman



More information about the Haskell-prime mailing list