Re: the MPTC Dilemma (please solve)

2006-03-23 Thread Roman Leshchinskiy

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

___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://haskell.org/mailman/listinfo/haskell-prime


seq as a class method

2006-03-23 Thread Wolfgang Jeltsch
Hello,

it seems that there is not yet a ticket about putting seq into a type class 
(again).

In my opinion, having seq available for every type is a serious flaw.  One 
problem is that the law f = \x - f x doesn't hold anymore since the equation 
is false for f = _|_.  There was also a discussion on one of the mailing 
lists some time ago which revealed that the Monad instance for IO doesn't 
satisfy the monad laws because of the availability of seq for IO, I think.

In addition, the automatic definition of seq for every type can make 
implementation details visible which were thought of as completely hidden.  
For example, it might make a difference whether one uses data or newtype for 
a one-alternative-one-field datatype, even if the data constructor is hidden.

I therefore propose to declare a class like this:

class Seq a where
seq :: a - b - b

(Perhaps the class name should be chosen better.)  Generation of standard 
instances should be supported via deriving clauses or Template Haskell.  For 
an algebraic datatype declared via

data T a1 ... an = C1 t11 ... t1m1 | ... | Ck tk1 ... tkmk

the implementation of seq should be something like this:

seq (C1 _ ... _) = id
seq _ = id

What do others think?

Best wishes,
Wolfgang
___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://haskell.org/mailman/listinfo/haskell-prime


Re: the MPTC Dilemma (please solve)

2006-03-23 Thread Roman Leshchinskiy

On Thu, 23 Mar 2006, Claus Reinke wrote:

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.


if we could actually write the instance implementations, it would be easier
to say whether this is an adequate approach. once the phantom types are 
connected to the actual types used in the implementation, I suspect this

would be very similar to the use of structure sharing and signature inclusion
in the ML implementation.


I would consider relying on any similarities between Haskell's data types 
and ML structures to be a bad thing, since the two are entirely different 
beasts. In particular, although the phantom types trick works to an 
extent, it is highly problematic from the software engineering point of 
view. Suppose I have a library which defines a monomorphic IntGraph type 
with specific vertex and edge types and does not know nor care about my 
Graph class. With your approach, I have to do something like


  data IntGraph' v e = IG IntGraph
  type MyIntGraph = IntGraph' Int (Int,Int)

declare all the instances and provide an impedance matching module which 
provides all IntGraph operations (which I want to use in addition to the 
Graph operations) for MyIntGraph. With ATs, I just have to do


  instance Graph IntGraph where
type Vertex IntGraph = Int
type Edge   IntGraph = (Int,Int)

ML structures are equally easy to use.


it is, however, probably as close as we can come within current Haskell,
In what sense is this current Haskell? 


ignoring accidental limitations in current implementations.


Are you sure that all these limitations really are accidential?

thanks. I'm not saying that ATS are a  bad thing, either, just that once we 
have a proper basis on which to rid current FD implemenations of accidental 
limitations, we should be able to implement ATS as a syntax transformation.


Even if it is possible to push FDs far enough to be able to translate ATs 
into them, why would you want to do so in the context of Haskell's 
development (it is certainly an interesting theoretical question, though)?
Having both mechanisms in one language doesn't seem to be a good idea to 
me and ATs seem to fit much better with the rest of Haskell and, 
consequently, are much easier to program with.



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

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


a variation of problem (a) above: contexts can introduce new, FD-bound
variables only in type signatures at the moment, not in class or data 
declarations.


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

otherwise, we could omit the spurious v parameter, as we'd like to.


I presume you are suggesting

  data Vertex g v = VertexPair g = VP v v

This would only affect the type of VP. Suppose we have

  rank :: (Vertex g v, Graph g) = g - v - Int

Presumably, we could then write

  rankFst :: Graph g = g - VertexPair g - Int
  rankFst g (VP v1 v2) = rank g v1

How does rankFst get the dictionary for Vertex g v which it must pass to 
rank (in a dictionary-based translation, at least)? It can be extracted 
from the Graph dictionary, but how does the compiler know?


Alternatively, we might try

  data VertexPair g = forall v . Vertex g v = VP v v

but now fstVertex doesn't work anymore (for reasons which, IIRC, are not 
accidential). These problems disappear with ATs (I think) as here, only 
the Graph dictionary is required by all operations.


Roman

___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://haskell.org/mailman/listinfo/haskell-prime


Re: Strict tuples

2006-03-23 Thread Wolfgang Jeltsch
Am Mittwoch, 22. März 2006 14:19 schrieb Bulat Ziganshin:
 Hello Wolfgang,

 you said WHAT you think but not said WHY? my motivation is to be able
 to use myriads of already implemented algorithms on new datatypes

I think, I already tried to explain why I think the way I think in an earlier 
mail:

 Strictness has to refer to attributes (the things you apply a data
 constructor to).  In you approach, strictness is connected to type
 arguments.  This causes problems.  For example, if you have

 data T a = C a a,

 what would T !a mean?  Would both attributes be strict?  But how would you 
 force only one attribute to be strict then?

By the way, would it be okay for you to answer below the quotation, not above 
it?  And would it be possible to use just a  sign, followed by a space for 
marking quotations.  My MUA gets confused by things like “WJ ”. Thank you 
very much.

 [...]

Best wishes,
Wolfgang
___
Haskell-prime mailing list
Haskell-prime@haskell.org
http://haskell.org/mailman/listinfo/haskell-prime