Re: type errors

1998-06-30 Thread Martin Stein

> Actually I think you would be better off with a class like
> this:
> 
>   class (Eq key, Ord key) => Dictionary dict key where
>  delete :: key -> dict dat -> dict dat
>  search :: key -> dict dat -> (key, SearchResult dat, dict dat)
>  searchList :: [key] -> dict dat -> ([(key,SearchResult dat)],dict dat)

Ok, I did not reconize this solution, it seems to me the (nearly) proper one.
But why not write:

   class => Dictionary dict where
   delete :: (Eq key, Ord key) => key -> dict key dat -> dict key dat
   ...

So one could avoid multiparamter classes at all. The two types key and dat
should be inferred by the type of dict (which is expressed by 'dict key dat'). I
can't think about a dictionary where key or dat are not associated with dict.

Martin Stein





RE: type errors

1998-06-30 Thread Mark P Jones

| > > class (Eq key, Ord key) => Dictionary dict key dat where
| > >  delete :: key -> dict -> dict
| ...
| > the first error:
| > 
| > Class type variable `dat' does not appear in method signature
| > delete :: key -> dict -> dict
| > 
| > Why does ghc expect that I use all of the type variables?
| > Obviously I only need
| > the key to remove an entry of a dictionary.
| 
| You're right.  The restriction is excessive.  Thanks for pointing
| this out.  Probably we should only require that at least one
| of the class variables is constrained.

I don't see this.  The fact is that, if any of the variables in the
class header don't appear in the type of a method, then that method
will always have an ambiguous type.  In this case, that would be:

   delete :: (Dictionary dict key dat) => key -> dict -> dict

Overloading is usually resolved by looking at the context in which
an identifier is used (in other words, by looking at the types that
a functions arguments and results are expected to have).  The problem
with this example is that there will never be any way for the type
system to determine which value the type variable `dat' should take.
Technically, this results in a loss of coherence (i.e., an undefined
semantics) for any program involving the function delete.  The type
checker might as well flag the declaration of delete as an error,
because you won't ever be able to use it without producing an error.

The solution to such problems is usually to create a small hierarchy
of classes (with different numbers of parameters) such as:

  class DictWithDelete key dict where
  delete :: key -> dict -> dict

  class DictWithDelete key dict => Dictionary key dict dat where
  add :: key -> dat -> dict -> dict
  etc...

However, in this case, using a constructor class as Simon suggested is
almost certainly the best approach.

I don't see how Simon's suggestion of replacing "all" with "at least one"
could be made to work in general.  Such an approach is however possible
if you are working with multiple parameter classes where the variables in
one parameter are determined directly by the parameters in another.
For example, consider the following class:

   class Collection elem col where
   empty :: col
   add   :: elem -> col -> col
   del   :: elem -> col -> col
   enum  :: col -> [elem]

By the argument above, one should expect empty to be rejected as having
an ambiguous type:  Collection elem col => col.   However, we could also
imagine modifying the definition of ambiguity to take account of the fact
that, in practice, the value of elem would probably be uniquely determined
by the value of col, and hence the context in which empty is used could
still provide enough information to allow the overloading to be resolved.
This is one of the key ideas behind Chen, Hudak and Odersky's proposal
for parametric classes.  The weaker notion of ambiguity here is just what
the AV operator (in my own thesis) was about.  Note that this would require
a new extension to the syntax of class declarations; at the moment, there
is no way to express any kind of dependency between the parameters of a
class.  (Nor are there mechanisms in the compilers to enforce them!)

All the best,
Mark





Re: Multi-parameter type classes

1998-06-30 Thread Andreas Rossberg

Simon L Peyton Jones wrote:
> 
> GHC 3.02 supports multi-parameter type classes, but I have been
> guilty of not documenting precisely what that means.
> 
> I've now summarised the extensions, informally but I hope
> precisely, at
> 
> http://www.dcs.gla.ac.uk/multi-param.html

That does not seem to be the correct URL. I had better luck with:

http://www.dcs.gla.ac.uk/~simonpj/multi-param.html


- Andreas





Multi-parameter type classes

1998-06-30 Thread Simon L Peyton Jones


Folks,

GHC 3.02 supports multi-parameter type classes, but I have been
guilty of not documenting precisely what that means.

I've now summarised the extensions, informally but I hope
precisely, at

http://www.dcs.gla.ac.uk/multi-param.html

This includes some changes that aren't in 3.02, based on 
people's experiences with 3.02.

I'd be very glad of feedback.  In effect, this is a straw-man
proposal for Haskell 2.

Simon






Re: type errors

1998-06-30 Thread Simon L Peyton Jones

> The ghc compiler complains about 2 type errors in the following code:
> 
> > data SearchResult a = Found a | Fail
> >
> > class (Eq key, Ord key) => Dictionary dict key dat where
> >  delete :: key -> dict -> dict
> >  search :: key -> dict -> (key,SearchResult dat,dict)
> >  searchList :: [key] -> dict -> ([(key,SearchResult dat)],dict)
> >
> >  searchList [] d = ([],d)
> >  searchList (x:xs) d = let (sresults,d') = searchList xs d
> >(x',sresult,d'') = search x d'
> >new_sres = (x',sresult):sresults
> >in (new_sres,d'')
> 
> the first error:
> 
> Class type variable `dat' does not appear in method signature
> delete :: key -> dict -> dict
> 
> Why does ghc expect that I use all of the type variables?
> Obviously I only need
> the key to remove an entry of a dictionary.

You're right.  The restriction is excessive.  Thanks for pointing
this out.  Probably we should only require that at least one
of the class variables is constrained.

Actually I think you would be better off with a class like 
this:

  class (Eq key, Ord key) => Dictionary dict key where
 delete :: key -> dict dat -> dict dat
 search :: key -> dict dat -> (key, SearchResult dat, dict dat)
 searchList :: [key] -> dict dat -> ([(key,SearchResult dat)],dict dat)

That is, you don't need the 'dat' type variable the class at all.

> Ambiguous type variable(s)
> `key', `dict'
> in the constraint `Dictionary dict key a10v'
> arising from use of `searchList' at Dtest2.hs:11
> In an equation for function `searchList':
> searchList (x : xs) d
>= let
>(sresults, d') = searchList xs d
>(x', sresult, d'') = search x d'
>new_sres = (x', (sresult)) : sresults
>  in (new_sres, (d''))
> In the definition for method `searchList'

You don't say which version of the compiler you are using,
but I think this a palpable bug in 3.01 that is fixed in 3.02.
So you are right to be confused by it!

Simon





Empty arrays

1998-06-30 Thread Jon . Fairbairn

Another little quibble:

If I run the following

> module Main where
> import Array

> main = (putStr . show . bounds . array (0,-1)) ([]::[(Integer,Char)])

with ghc I get (0, -1), but with hugs I get 

Program error: index: Index out of range

As far as I can interpret the library report, ghc is correct in this
respect.  Moreover, I think that is what we should get, since an empty
array is useful.  So perhaps I should simply be reporting a bug in
hugs, but I thought I'd check here to be sure that everyone agrees
that this is correct.

   Jon

-- 
Jon Fairbairn [EMAIL PROTECTED]







Re: type errors

1998-06-30 Thread Philip Wadler

  You're right.  The restriction is excessive.  Thanks for pointing
  this out.  Probably we should only require that at least one
  of the class variables is constrained.

Why even require this?  (All x) => x -> x uses the class `All'
which restricts its argument not one whit.  -- P