Re: Haskell 1.3

1996-04-22 Thread peterson-john

We are still in the middle of a bunch of minor last-minute changes.
While the technical aspects of Haskell 1.3 are stable, we're still
fiddling with the prelude and the wording of the report.  We've now
set a `final' final release date at May 1.  As before, the working
version of the report is available via the web at 

http://haskell.cs.yale.edu/haskell-report/haskell-report.html

More importantly, there is a lot of work going on to get the
implementations ready.  I hope people will be able to start using
Haskell 1.3 soon after we release the report.

John Peterson
[EMAIL PROTECTED]
Yale Haskell Project







Re: Haskell 1.3

1996-03-08 Thread Ron Wichers Schreur

Lennart Augustsson wrote:

> It looks ugly, but we could say that a data declaration does not 
> have to have any constructors:
> 
>   data Empty =

Philip Wadler responded:

> I'm not keen on the syntax you propose.  How about if we allow the
> rhs of a data declaration to be just `empty', where `empty' is a
> keyword?
>
> data Empty = empty

Another suggestion is to omit the equal sign, as in

  data Empty


Cheers,

Ronny Wichers Schreur
[EMAIL PROTECTED]








Re: Haskell 1.3

1996-03-08 Thread Magnus Carlsson


Philip Wadler writes:
 > 
 > > It looks ugly, but we could say that a data declaration does not 
 > > have to have any constructors:
 > > 
 > >data Empty =
 > > 
 > >-- Lennart
 > 
 > I agree that the best way to fix this is to have a form of data
 > declaration with no constructors, but I'm not keen on the syntax you
 > propose.  How about if we allow the rhs of a data declaration to be
 > just `empty', where `empty' is a keyword?
 > 
 >  data Empty = empty
 > 
 > -- P

I would like to propose an alternative that in my view has both good
syntax, and does not introduce a new keyword:

   data Empty

/Magnus






Re: Haskell 1.3

1996-03-08 Thread Philip Wadler


> It looks ugly, but we could say that a data declaration does not 
> have to have any constructors:
> 
>   data Empty =
> 
>-- Lennart

I agree that the best way to fix this is to have a form of data
declaration with no constructors, but I'm not keen on the syntax you
propose.  How about if we allow the rhs of a data declaration to be
just `empty', where `empty' is a keyword?

data Empty = empty

-- P






Re: Haskell 1.3

1996-03-08 Thread Lennart Augustsson



> Suggestion: Include among the basic types of Haskell a type `Empty'
> that contains no value except bottom.
Absolutely!  But I don't think it should be built in
(unless absolutely necessary).

It looks ugly, but we could say that a data declaration does not 
have to have any constructors:

data Empty =

   -- Lennart

PS. There are other ways of getting empty types, but they are
all convoluted, like

data Empty = Empty !Empty






Re: Haskell 1.3

1996-03-08 Thread Lennart Augustsson



> Suggestion: Include among the basic types of Haskell a type `Empty'
> that contains no value except bottom.
Absolutely!  But I don't think it should be built in
(unless absolutely necessary).

It looks ugly, but we could say that a data declaration does not 
have to have any constructors:

data Empty =

   -- Lennart

PS. There are other ways of getting empty types, but they are
all convoluted, like

data Empty = Empty !Empty






Re: Haskell 1.3: modules & module categories

1995-10-12 Thread Manuel Chakravarty


>Date: Mon, 2 Oct 1995 05:53:44 -0400
>Reply-To: [EMAIL PROTECTED]
>From: Manuel Chakravarty <[EMAIL PROTECTED]>
> 
>> To me, one of the most regrettable characteristics of
>> the Algolic family of languages is the tendency of the
>> compiler to turn into a giant black box of facilities
>> open only to an elite minority of compiler hackers, which
>> then begins inexorably sucking the entire programming
>> support environment down its event horizon.
>>
>> I would much prefer that the concept of "compiler" in this
>> sense did not exist, and that instead one had a nicely
>> factored translation toolset wide open to the application
>> programmer.  Lisp and Forth begin to approach this ideal.
> 
> Would you mind divulging the identity of your hilarious correspondent?

I got the impression that his original mail was distributed to the whole
Haskell mailing list. Anyway, I append it at this message.

Cheers,

Manuel

P.S.: As it seems that there are a number of people who didn't get the mail I
  responded to, I CC this to the whole mailing list. Sorry, for any
  duplicates. 

---
Date: Sat, 30 Sep 1995 10:09:08 -0700
From: [EMAIL PROTECTED] (Jeff Prothero)
To: [EMAIL PROTECTED]
Subject: Re: Haskell 1.3: modules & module categories
Cc: [EMAIL PROTECTED]


Manuel Chakravarty <[EMAIL PROTECTED]> writes:

| [...] it is desirable to be able to
| restrict the access to some modules in a way that the
| compiler can control when a group of people is working
| in one module hierarchy. Too illustrate this, assume
| that we classify the modules into different levels of
| abstraction, say, three levels: [...]

To me, one of the most regrettable characteristics of
the Algolic family of languages is the tendency of the
compiler to turn into a giant black box of facilities
open only to an elite minority of compiler hackers, which
then begins inexorably sucking the entire programming
support environment down its event horizon.

I would much prefer that the concept of "compiler" in this
sense did not exist, and that instead one had a nicely
factored translation toolset wide open to the application
programmer.  Lisp and Forth begin to approach this ideal.

At the least, it would be very nice if the compiler
could be kept distinct enough from the rest of the
programming support environment that it doesn't begin
sucking what sound to me like logically separate
project management concerns (above) into its orbit.

Would it be possible to define an interface which
allows the above sort of "Not if you're a left-handed
programmer and it's Tuesday" restrictions to be
separately implemented and kept out of the core
language?

(To my mind, one of the successes of C -- as distinct from
C++, say -- is that it clearly defined what was and wasn't
the task of the compiler, and stuck to its guns, resulting
in that very rare bird:  An Algolic language with a stable
language definition and compiler.)







Re: Haskell 1.3: modules & module categories

1995-10-10 Thread David Espinosa




   Date: Mon, 2 Oct 1995 05:53:44 -0400
   Reply-To: [EMAIL PROTECTED]
   From: Manuel Chakravarty <[EMAIL PROTECTED]>

   > To me, one of the most regrettable characteristics of
   > the Algolic family of languages is the tendency of the
   > compiler to turn into a giant black box of facilities
   > open only to an elite minority of compiler hackers, which
   > then begins inexorably sucking the entire programming
   > support environment down its event horizon.
   >
   > I would much prefer that the concept of "compiler" in this
   > sense did not exist, and that instead one had a nicely
   > factored translation toolset wide open to the application
   > programmer.  Lisp and Forth begin to approach this ideal.

Would you mind divulging the identity of your hilarious correspondent?

David





Re: Haskell 1.3: modules & module categories

1995-10-02 Thread Johannes Waldmann


> > With present Haskell modules, it seems that `with'
> > automatically comes with `use' and clutters up your namespace.
> > That's why you sometimes need re-naming when importing.

Sorry, I missed that one. Manuel pointed out that with/use 
is already contained in the `qualified names'-proposal.
When I'm comparing Haskell to Ada, it seems that basically

import Foo  = with Foo; use Foo;
import qualified Foo= with Foo;

Still I'd like to have Ada's `use' on its own, as in

with Text_Io;
package Foo is
  ...
  procedure Bar is
use Text_Io; 
  begin
...
  end;
  ...
end Foo;

And while we're at it, what about
- nested modules
- with possibly private sub-modules
similar to the Ada(-95) things.

-- 
Johannes Waldmann, Institut f\"ur Informatik, UHH, Jena, D-07740 Germany,
(03641)  630793  [EMAIL PROTECTED]  http://www.minet.uni-
jena.de/~joe/ ...  Im naechsten Heft: Als Arbeiter in einer Radiofabrik -
Freundschaft mit dem Sohn  eines Luftwaffengenerals - Das  KGB ueberwacht
den Amerikaner auf Schritt und  Tritt - Alarmierende Verdachtsmomente bei
der Kaninchenjagd - Ungluecklich verliebt in eine rothaarige Juedin





Re: Haskell 1.3: modules & module categories

1995-10-02 Thread Johannes Waldmann


Has the Ada solution been properly considered? What I really like about
Ada packages is that you have `with' and `use' as separate operations
(on namespaces). Typical (simplified) examples are:

Put_Line ("Foo."); -- won't work

with Text_Io; Text_Io.Put_Line ("Foo."); -- will work

with Text_Io; Put_Line ("Foo."); -- won't work

with Text_Io; use Text_Io; Put_Line ("Foo."); -- will work

use Text_Io; Put_Line ("Foo."); -- won't work

That is, `with Bar' makes module Bar's namespace accessible,
but prefixed with that module's name. On the other hand, 
`use Bar' adds `Bar.' to a set of default prefixes that are
tried when looking up names from then on. If an ambiguity arises,
the compiler complains. You may resolve this by using the prefixed name.

You can only `use' what you have `with'ed,
and all `with's have to go at the very start of a module,
so you (or a configuration management system) 
can easily check on what packages your code depends.

With present Haskell modules, it seems that `with'
automatically comes with `use' and clutters up your namespace.
That's why you sometimes need re-naming when importing.

(As I'm mostly using Gofer/Hugs, you may imagine that I'm not so
sure about Haskell modules. However, I _do_ like the Ada solution.
Please correct me if the above is basically wrong or inapplicable.)

-- 
Johannes Waldmann, Institut f\"ur Informatik, UHH, Jena, D-07740 Germany,
(03641)  630793  [EMAIL PROTECTED]  http://www.minet.uni-
jena.de/~joe/ ...  Im naechsten Heft: Als Arbeiter in einer Radiofabrik -
Freundschaft mit dem Sohn  eines Luftwaffengenerals - Das  KGB ueberwacht
den Amerikaner auf Schritt und  Tritt - Alarmierende Verdachtsmomente bei
der Kaninchenjagd - Ungluecklich verliebt in eine rothaarige Juedin





Re: Haskell 1.3: modules & module categories

1995-10-02 Thread Manuel Chakravarty


> To me, one of the most regrettable characteristics of
> the Algolic family of languages is the tendency of the
> compiler to turn into a giant black box of facilities
> open only to an elite minority of compiler hackers, which
> then begins inexorably sucking the entire programming
> support environment down its event horizon.
> 
> I would much prefer that the concept of "compiler" in this
> sense did not exist, and that instead one had a nicely
> factored translation toolset wide open to the application
> programmer.  Lisp and Forth begin to approach this ideal.

I am a bit puzzled about this statement. I used to think about Lisp
environments just in the same way that you characterize the compilers for
Algol-style languages. The typical Common Lisp environment is one big engine
with thousands of features and it takes a rather long time to get to the status
of an experienced user. Maybe it is a matter of familiarity with either style
of environment.

> Would it be possible to define an interface which
> allows the above sort of "Not if you're a left-handed
> programmer and it's Tuesday" restrictions to be
> separately implemented and kept out of the core
> language?

I am not sure if you can separate these issues, but there is one important
requirement. There must not be an easy or even moderately difficult way to
circumvent the restrictions. As they say, there is always a bad programmer in
your team.

Cheers,

Manuel





Re: Haskell 1.3: modules & module categories

1995-09-30 Thread Ming Yang


If you could email me the piece of code you are having this
problem, I can look at it and try to see what is wrong.
-- Ming





Re: Haskell 1.3

1995-09-20 Thread wadler


JL writes,

   A formal treatment of parametricity in the presence of overloading
   has not been written up (Eric Meijer has talked of doing so). The
   problem with writing it up is that it's too simple: it reduces to a
   single observation, namely that the parametricity theorem coming
   from an overloaded type is the regular parametricity theorem that
   arises after performing the dictionary expansion.

You can find this observation in Section 3.4 of the original
`Theorems for Free'.  So it is written up!  -- P





Re: Haskell 1.3 (newtype)

1995-09-19 Thread wadler


Sebastian suggests using some syntax other than pattern
matching to express the isomorphism involved in a newtype.
I can't see any advantage in this.

Further, Simon PJ claims that if someone has written

data Age = Age Int
foo (Age n) = (n, Age (n+1))

that we want to be able to make a one-line change

newtype Age = Age Int

leaving all else the same: in particular, no need to add
twiddles, and no changes of the sort Sebastian suggests.
I strongly support this!  (No, Simon and I are not in collusion;
indeed, we hardly ever talk to each other!  :-)

Cheers,  -- P





Re: Haskell 1.3 (newtype)

1995-09-19 Thread Ryszard Kubiak


In a recent message Sebastian Hunt suggests a solution to the 'newtype'
problem. Let me recall another approach which can cure several things at a
time (probably introducing new problems though).

Some time ago Mark Jones wrote a paper " From Hindley-Milner Types to
Modular Structures". He suggested introducing record types like

  type Point = {x,y: Real}

If we define records to be unlifted then the type Int and {int: Int}
will be isomorphic and there is no reason to introduce a special 'newtype'
syntax. There is a problem with class instances - type synonyms are not
allowed there. May be, the restriction could be relaxed to allow
types defined as structures to be subject to instantiating.

It's worth noting that with Mark's ideas the records of the 1.3 proposal
can be replaced by something more general - another step forward.

I don't like neither 'newtype' nor the records of Haskell 1.3. Both mean a
lot of syntax with little semantics. Even if Mark's ideas seem premature at
this stage it's worth working on them and not introducing some bad syntax
to be withdrawn from the language later. Removing even the worst syntax
>from a language is always a painful process, vide the n+k patterns.

Rysiek

PS. I've written the above without Mark's permit. Sorry, Mark, it was too
difficult for me to wait...

 

 







Re: Haskell 1.3 (newtype)

1995-09-19 Thread Sebastian Hunt


I think that the following points have emerged from the recent discussion 
about the proposed newtype declaration:

1) Pattern matching against strict constructors will result in 
   functions which are strict in the annotated constructor argument. For 
   example:

data T = A !Int

f :: T -> Bool
f (A n) = True

   results in f such that

f (A undefined) = undefined

   This results in a loss of referential transparency because, before we can 
   replace f (A e) by True, we must check that e is not undefined. Of 
   course, a transformation in this direction can only make a program more 
   defined, so perhaps we should be more worried by the fact that it would 
   be unsafe to replace True by f (A e), in general.

2) It would be wrong to define the proposed

newtype N = B G

   declaration as being equivalent to

data N = B !G

   because a) it will restrict its use to G such that !G makes sense, and b) 
   programmers will be tripped up by the strict pattern matching semantics 
   above.

On reflection, I think I agree with point 2, so if the proposed newtype 
syntax is adopted it will need to be given a semantics independently of 
that of strict constructors, as Simon has described.

On the other hand, it also seems to me that the reason this discussion 
started is that the proposed newtype syntax hijacks the constructor 
syntax for a new purpose: the definition of an isomorphism. Since the 
declaration

newtype N = B G

means "let N be isomorphic to G and let B :: G -> N be one half of the
isomorphism" it is clear that B is not a constructor in the usual sense at
all. In Haskell and its antecedents (though not in the general setting of
term rewriting systems) it is well established that for

f (B e) = ...

to be legal, B must be a constructor (with the consequence that f is
strict). The proposed newtype syntax is a significant departure from 
this.

Would it really be so inconvenient if pattern matching couldn't be used 
for the iso from G to N? How about a syntax which made both halves of the 
isomorphism explicit?

newtype in :: N <-> G :: out

The example from the earlier postings would then be rendered as

newtype in :: Arg <-> Int :: out

foo :: Arg -> (Int, Arg)
foo a = (n, in (n + 1)), where n = out a

Implementations would be free to implement in and out as id

foo a = (n, id (n + 1)), where n = id a

and then magic them away

foo a = (a, a + 1)

Sebastian Hunt





Re: Haskell 1.3 (newtype)

1995-09-14 Thread Simon L Peyton Jones



Phil says:

| I think its vital that users know how to declare a new isomorphic
| datatype; it is not vital that they understand strictness declarations.
| Hence, I favor that
| 
|   newtype Age = Age Int
|   data Age = Age !Int
| 
| be synonyms, but that both syntaxes exist.
| 
| This is assuming I have understood Lennart correctly, and that
| 
|   foo (Age n) = (n, Age (n+1))
|   foo' a = (n, Age (n+1)) where (Age n) = a
| 
| are equivalent when Age is declared as a strict datatype. Unlike
| Sebastian or Simon, I believe it would be a disaster if for a newtype
| one had to distinguish these two definitions.

I agree that it is rather undesirable for them to differ.  If
someone had declared a *non-strict* verion like this:

data Age = Age Int
foo (Age n) = (n, Age (n+1))

(where foo is patently non-strict in n), and then just wanted to say "do
away with the Age constructor", I'd like it to be a one-line change (data
--> newtype), rather than also having to add a twiddle to every
pattern-match:

foo ~(Age n) = (n, Age (n+1))

[which is eqiuvalent to using a where binding]

In effect, newtype could be explained as (a) a data decl with a !, and (b)
adding a ~ to every pattern match.

This is a hard one to call: which version actually requires least
explanation?!

Simon







Re: Haskell 1.3 (newtype)

1995-09-13 Thread Sebastian Hunt


On Wed, 13 Sep 1995 [EMAIL PROTECTED] wrote:

> Well, I'm glad to see I provoked some discussion!
...
> Why should foo evaluate its argument?  It sounds to me like
> Lennart is right, and I should not have let Simon lead me astray!
... 
> This is assuming I have understood Lennart correctly, and that
> 
>   foo (Age n) = (n, Age (n+1))
>   foo' a = (n, Age (n+1)) where (Age n) = a
> 
> are equivalent when Age is declared as a strict datatype. Unlike
> Sebastian or Simon, I believe it would be a disaster if for a newtype
> one had to distinguish these two definitions.

I don't see how these two can be equivalent, unless a special case is 
made in the semantics for data types with a single constructor when the
constructor happens to be strict. Consider

data G = F !Int | D Int

f :: G -> Bool
f (D _) = True
f (F _) = False

If Lennart is right about foo, doesn't it follow that

f (D undefined) = True?

In which case, since D is strict, we have

f undefined = f (D undefined) = True

and so, by monotonicity of f, f v = True for all v and, in particular,

f (F e) = True

This can't be right, surely?

Sebastian





Re: Haskell 1.3 (newtype)

1995-09-13 Thread wadler


Well, I'm glad to see I provoked some discussion!

Simon writes:

   Lennart writes:
   
   | So if we had
   | 
   |data Age = Age !Int
   |foo (Age n) = (n, Age (n+1))
   | 
   | it would translate to
   | 
   |foo (MakeAge n) = (n, seq MakeAge (n+1))
   | 
   | [makeAge is the "real" constructor of Age]
   
   Indeed, the (seq MakeAge (n+1) isn't eval'd till the second
   component of the pair is.  But my point was rather that foo
   evaluates its argument (MakeAge n), and hence n, as part of its
   pattern matching.  Hence foo is strict in n.

Why should foo evaluate its argument?  It sounds to me like
Lennart is right, and I should not have let Simon lead me astray!

I think its vital that users know how to declare a new isomorphic
datatype; it is not vital that they understand strictness declarations.
Hence, I favor that

newtype Age = Age Int
data Age = Age !Int

be synonyms, but that both syntaxes exist.

This is assuming I have understood Lennart correctly, and that

foo (Age n) = (n, Age (n+1))
foo' a = (n, Age (n+1)) where (Age n) = a

are equivalent when Age is declared as a strict datatype. Unlike
Sebastian or Simon, I believe it would be a disaster if for a newtype
one had to distinguish these two definitions.

Cheers,  -- P
   





Re: Haskell 1.3 (newtype)

1995-09-13 Thread Simon L Peyton Jones



Lennart writes:

| So if we had
| 
|   data Age = Age !Int
|   foo (Age n) = (n, Age (n+1))
| 
| it would translate to
| 
|   foo (MakeAge n) = (n, seq MakeAge (n+1))
| 
| [makeAge is the "real" constructor of Age]
| 
| Now, surely, seq does not evaluate its first argument when the
| closure is built, does it?  Not until we evaluate the second component
| of the pair is n evaluated.

Indeed, the (seq MakeAge (n+1) isn't eval'd till the second component
of the pair is.  But my point was rather that foo evaluates its argument
(MakeAge n), and hence n, as part of its pattern matching.  Hence
foo is strict in n.

Sebastian writes:

| Is it really a good idea to extend the language simply to allow foo and 
| foo' to be equivalent? The effect of foo' can still be achieved if Age is 
| a strict data constructor:
| 
|   data Age = Age !Int
|
|   foo'' :: Age -> (Int, Age)
|   foo'' a = (n, Age (n+1)) where (Age n) = a
| 
| and compilers are free (obliged?) to represent a value of type Age by an
| Int.

Indeed, it's true that foo'' does just the right thing.  Furthermore, I
believe it's true that given the decl

data T = MkT !S

the compiler is free to represent a value of type T by one of type S (no
constructor etc).

Here are the only real objections I can think of to doing "newtype" via a
strict constructor. None are fatal, but they do have a cumulative effect.

1. It requires some explanation... it sure seems a funny way to
   declare an ADT!

2. The programmer would have to use let/where bindings to project values
>from the new type to the old, rather than using pattern matching.  Perhaps
not a big deal.

3. We would *absolutely require* to make (->) an instance of Data.  It's
   essential to be able to get

data T = MkT !(Int -> Int)

4. We would only be able to make a completely polymorphic "newtype" if
we added a quite-spurious Data constraint, thus:

data Data a => T a = MkT !a

(The Data is spurious because a value of type (T a) is going to be
represented by a value of type "a", and no seqs are actually going to be
done.)

5.  We would not be able to make a newtype at higher order:

data T k = MkT !(k Int)

because there's no way in the language to say that (k t) must be in class
Data for all t.  

[This is a somewhat subtle restriction on where you can put strictness
annotations, incidentally, unless I've misunderstood something.]


Simon
   





Re: Haskell 1.3 (Bounded;fromEnum;type class synonyms)

1995-09-12 Thread reid



Dear Sverker Nilsson,

Thanks for your message - interesting ideas and interesting questions.
[I'm copying the reply to the Haskell mailing list in case anyone
wishes to support your suggestions.]

First, one of Haskell's annoying features is that the scope of a type
variable in a type signature or instance heading only extends over the
signature.  So, when you want to write:

> instance (FromInt a, ToInt a, MinVal a, MaxVal a) => Enum a where
> enumFrom c = map fromInt [toInt c .. toInt (maxVal :: a)]

It doesn't work (because the "a" isn't in scope during the
declarations) - you have to use "asTypeOf" instead:

> instance (FromInt a, ToInt a, MinVal a, MaxVal a) => Enum a where
> enumFrom c = map fromInt [toInt c .. toInt (maxVal `asTypeOf` c)]


While developing something like the proposed "Bounded" class, 
you introduced separate classes for minVal and maxVal observing:

> Something having a minimum value, in my view, didn't necessarily
> imply it would have a maximum value.

Yes, perfectly true.  The best example is that there's a minimal list
(the empty list) but even though there's a maximal Char (say), there's
no maximal list of characters.  

Our primary motivation for adding Bounded is to clean up the
{min,max}{Char,Int} situation and make the derived Enum instances
slightly more regular (similar in spirit to your definitions above).
For this purpose, insisting on having both a min and a max isn't a
problem.

However, for other purposes, having one bound but not the other is
certainly possible and maybe useful.  

(I agree that defining a bogus instance in which "minVal" (say) is
defined but "maxVal" is undefined or has a bogus value is at least
untidy and at worst a bug waiting to happen.  I tried (and failed) to
get the Text instance of (a -> b) removed from the Prelude for this
reason.)


The major disadvantage of separating the two is that it introduces
even more classes.

If you read the preludechanges document carefully, you'll see that
(even at this late stage) these are only proposed changes.  Glasgow
argue that it's hard enough to keep Ix and Enum separate in your mind
- adding another can only worsen things.


You were then surprised and disturbed to find that this isn't legal
Haskell:

> class (MinVal a, MaxVal a)=>Bounded a
> 
> instance Bounded T where
>maxVal = T3
>minVal = T1

There was a proposal to make this legal.  As far as I know, there's no
technical problems here - I guess it just got forgotten about (or the
proposer decided that Haskell 1.3 had too many changes in it already!)


> * Should Bounded be derived from Ord?
> 
> The Bounded class that was suggested for Haskell 1.3 was derived from
> Ord. Myself playing with similar things I derived MinVal and MaxVal
> from nothing - I thought this more general. Maybe the reason for
> having Bounded derived from Ord was to imply that its functions shall
> satisfy certain laws, probably as being min/max as defined by the
> ordering functions in Ord. But as I don't see how this can be
> guaranteed by deriving Bounded from Ord, I would think that it could
> as well be standalone (or derived from something like MinBound and
> MaxBound if possible); for more generality and less dependency between
> the classes in the system.

Yes, the sole reason is because it seemed tidier to specify Ord -
without knowing which comparision is being used, it doesn't make much
sense to say you have a "maximum value".

> For example, the new proposal says:
> 
> > ...
> > Programmers are free to define a class for partial orderings; here, we
> > simply state that Ord is reserved for total orderings.
> 
> That seems to imply also that a programmer should not use Bounded on
> types that have no total ordering. I believe this might be an unnecessary
> restriction.

It certainly looks that way.

> > The names fromEnum and toEnum are misleading since
> > their types involve both Enum and Bounded.  We couldn't face writing 
> > fromBoundedEnum and toBoundedEnum.  Suggestions
> > welcome. 
> 
> Maybe names like ToInt and FromInt could be used for this?
>
> How about the following, assuming the proposed diff and succ functions:
> 
> class (Bounded a, Enum a) => ToInt a where toInt :: a -> Int [...]
> class (Bounded a, Enum a) => FromInt a where fromInt :: Int -> a [...]

These names look good.  Three _minor_ concerns:

1) It introduces even more standard classes to confuse programmers
   with.  Why allow the programmer to override them?

2) Several implementations have added a non-standard method 

 fromInt :: Int -> a

   to the Num class to avoid unnecessary uses of fromInteger.

   However, I think most normal uses would work unchanged if "fromInt"
   had type:

 fromInt :: (Bounded a, Enum a) => Int -> a

3) There is a weak tradition of putting the name of the class into the
   name of the method.

   This tradition is often broken when it would get in the way of a
   good name.

Action:

1) I'll remove the Ord c

Re: Haskell 1.3 (newtype)

1995-09-12 Thread Sebastian Hunt



On Tue, 12 Sep 1995, Lennart Augustsson wrote:

> The posted semantics for strict constructors, illustrated by this example
> from the Haskell 1.3 post, is to insert seq.
> 
> > data R = R !Int !Int
> > 
> > R x y = seq x (seq y (makeR x y)) -- just to show the semantics of R
> 
> So if we had
> 
>   data Age = Age !Int
>   foo (Age n) = (n, Age (n+1))
> 
> it would translate to
> 
>   foo (MakeAge n) = (n, seq MakeAge (n+1))
> 
> [makeAge is the "real" constructor of Age]

I had assumed (as Simon seems to) that the semantics of pattern matching 
against a strict constructor would accord with the following:

1.  matching a simple pattern involves evaluating the expression being 
matched to the point that its outermost constructor is known

2.  for strict constructors this must result in the annotated
constructor argument(s) being evaluated

>From what Lennart says, this is not the intended semantics. So what *is* 
the intended semantics?

Sebastian Hunt






Re: Haskell 1.3 (Bounded;fromEnum;type class synonyms)

1995-09-12 Thread Sverker Nilsson


* Playing around, learning the basics, reinventing the wheel...

I had been playing around with some classes, primarily to learn for
myself, being new to the Haskell language, when I got the report on
the current status of Haskell 1.3. The classes I had played with had
some similarities to some of the proposals for the new prelude, yet I
had made it in a quite different way. Trying to combine the two
styles, I ran into an unexpected problem. This problem I am naive
enough to believe could be solved by a simple language extension. 

Using Gofer, I had made some classes that could be used for
implementing ordering and other things for enumeration (data T=T1 |
T2 | T3) types but not restricted to those. I made 4 minimal classes
with just 1 function in each.  (I thought this would be most general.
Something having a minimum value, in my view, didn't necessarily
imply it would have a maximum value.) So:

class FromInt a where
fromInt:: Int->a

class ToInt a where
toInt:: a->Int

class MaxVal a where
maxVal:: a

class MinVal a where
minVal:: a

-- I then used this as follows:

data T = T1 | T2 | T3

instance ToInt T where
toInt e = case e of
T1 -> 1
T2 -> 2
T3 -> 3

instance Eq T where
a == b = toInt a == toInt b

instance Ord T where
a <= b = toInt a <= toInt b

-- And so on. The MaxVal and MinVal classes also where used to make a generic
-- implementation of a bounded Enum class, generalizing how it was made in the
-- Gofer prelude for Char:

instance (FromInt a, ToInt a, MinVal a, MaxVal a) => Enum a where
enumFrom c  = map fromInt [toInt c .. toInt (maxVal `asTypeOf` c)]
enumFromThen c c'   = map fromInt [toInt c, 
   toInt c' .. toInt (lastVal `asTypeOf` c)]
  where lastVal = if c' < c then minVal else maxVal


-- This worked to my great delight! And I had began to learn the basics
-- of the type system in Haskell. My only problem was that I had to use
-- (maxVal `asTypeOf` c) instead of (maxVal::a). I believe the reason
-- for this might be clear when I learn more. Somebody have a clue?

*   Running into a problem: type class synonyms are not synonymous?

Then, I got the report on the developments of Haskell 1.3 and began to read
it with great curiosity. I then found the Bounded class, containing
corresponding functions to MinVal and MaxVal. A question then occured to me:
Why not have separate classes as I had done? Would not that perhaps be more
general, increasing the possibilities for reuse? (Without having to stub out
one of minBound or maxBound if you use it for a type without one of them.)
On the other hand, I saw the convenience of having both minBound and maxBound
in the same class, decreasing the number of classes that have to be mentioned
in various cases. But I thought, then, why not derive the Bounded class
>from MinVal and MaxVal - would not that then be equivalent? So I tried

class (MinVal a, MaxVal a)=>Bounded a   -- This was allowed, but then...

instance Bounded T where
maxVal = T3
minVal = T1

-- That didn't work! (Gofer said: ERROR "tst.gs" (line 45): No member
 "maxVal" in class "Bounded") Maybe I had done something wrong, or Gofer
does not allow something that would be allowed in Haskell? I suspect
however that I am simply not supposed to do this in either Haskell or Gofer...

Instead I had to use two separate instantiaions, exactly as before
I declared the Bounded class:

instance MinVal T where
minVal = T1
instance MaxVal T where
maxVal = T3

This seems to be somewhat unnecessary, wouldn't it be quite possible
for a compiler to transform the instantiation of Bounded to the two
instantiations of MinVal and MaxVal?

Maybe this would be a useful development of Haskell?

*   Should Bounded be derived from Ord?

The Bounded class that was suggested for Haskell 1.3 was derived from
Ord. Myself playing with similar things I derived MinVal and MaxVal
>from nothing - I thought this more general. Maybe the reason for
having Bounded derived from Ord was to imply that its functions shall
satisfy certain laws, probably as being min/max as defined by the
ordering functions in Ord. But as I don't see how this can be
guaranteed by deriving Bounded from Ord, I would think that it could
as well be standalone (or derived from something like MinBound and
MaxBound if possible); for more generality and less dependency between
the classes in the system.

For example, the new proposal says:

> ...
> Programmers are free to define a class for partial orderings; here, we
> simply state that Ord is reserved for total orderings.

That seems to imply also that a programmer should not use Bounded on
types that have no total ordering. I believe this might be an unnecessary
restriction.

*   Can toInt be fromEnum and toEnum fromInt?

New functions fromEnum and toEnum were proposed to be added

Re: Haskell 1.3 (lifted vs unlifted)

1995-09-12 Thread smk


John Hughes mentioned a deficiency of Haskell:
  OK, so it's not the exponential of a CCC --- but 
  Haskell's tuples aren't the product either, and I note the proposal to 
  change that has fallen by the wayside. 

and Phil Wadler urged to either lift BOTH products and functions,
or none of them.

My two pence:
If functions/products are not products and exponentials of a CCC, you
should aim for the next best thing: an MCC, a monoidal closed category.
But Haskell's product isn't even monoidal:

There is no type I such that A*I and A are isomorphic.
The obvious candidate (in a lazy language) would be
the empty type 0, but A*0 is not isomorphic to A but to the lifting of A.

Another problem: the function space  A*B -> C  should be naturally
isomorphic to  A -> (B -> C).  What does the iso look like?
One half is the obvious curry function:

curry f x y = f(x,y)

But what is the other half?  Apparently, it should be either

uncurry1 f (x,y) = f x y

or

uncurry2 f (~(x,y)) = f x y

Which one is right depends on which one establishes
the isomorphism.  Consider the definition

f1 (x,y) = ()

Now:
uncurry1 (curry f1) undef =
undef =
f1 undef

while on the other hand:
uncurry2 (curry f1) undef =
curry f1 (p1 undef, p2 undef) =
f1(p1 undef,p2 undef) =
() =/=
f1 undef

This suggests that uncurry2 is wrong and uncurry1 is right, but for

f2 (~(x,y)) = ()

the picture is just the other way around.
BTW  It doesn't help to employ "seq" in the body of curry.


Looks rather messy.
Can some of this be salvaged somehow?

--
Stefan Kahrs





Re: Haskell 1.3 (newtype)

1995-09-12 Thread Lennart Augustsson



Simon, I think you're mistaken.

Simon writes:
> 
>   newtype Age = Age Int
>   
>   foo :: Age -> (Int, Age)
>   foo (Age n) = (n, Age (n+1))
> 
> Now, we intend that a value of type (Age Int) should be represented by
> an Int.  Thus, apart from the types involved, the following program should
> be equivalent:
> 
>   type Age' = Int
> 
>   foo' :: Age' -> (Int, Age')
>   foo' n = (n, n+1)
> 
> So is foo' strict in n? No, it isn't.  What about foo?  If newtype is just a
> strict data constructor, then it *is* strict in n.

The posted semantics for strict constructors, illustrated by this example
>from the Haskell 1.3 post, is to insert seq.

> data R = R !Int !Int
> 
> R x y = seq x (seq y (makeR x y)) -- just to show the semantics of R

So if we had

data Age = Age !Int
foo (Age n) = (n, Age (n+1))

it would translate to

foo (MakeAge n) = (n, seq MakeAge (n+1))

[makeAge is the "real" constructor of Age]

Now, surely, seq does not evaluate its first argument when the
closure is built, does it?  Not until we evaluate the second component
of the pair is n evaluated.

The other behaviour of strict constructors would worry me since we
would loose referential transparency.

I'm not opposing newtype, but an ordinary datatype with
one constructor with one strict argument is very similar.
The only way to distinguish them (and it is debatable if
this is what you want) is like this

data T = T !Int
f (T _) = True

newtype T' = T' Int
f' (T' _) = True

Now we get
f undefined ==> undefined
f' undefined ==> True

-- Lennart





Re: Haskell 1.3 (newtype)

1995-09-12 Thread Sebastian Hunt





On Tue, 12 Sep 1995, Simon L Peyton Jones wrote:

> 
> 
> Phil writes:
> 
> | Make newtype equivalent to a datatype with one strict constructor.
> | Smaller language, more equivalences, simpler semantics, simpler
> | implementation.  An all around win!
> 
> I believe it would be a mistake to do this!  Consider:
> 
>   newtype Age = Age Int
>   
>   foo :: Age -> (Int, Age)
>   foo (Age n) = (n, Age (n+1))
> 
> Now, we intend that a value of type (Age Int) should be represented by
> an Int.  Thus, apart from the types involved, the following program should
> be equivalent:
> 
>   type Age' = Int
> 
>   foo' :: Age' -> (Int, Age')
>   foo' n = (n, n+1)

Is it really a good idea to extend the language simply to allow foo and 
foo' to be equivalent? The effect of foo' can still be achieved if Age is 
a strict data constructor:

foo'' :: Age -> (Int, Age)
foo'' a = (n, Age (n+1)) where (Age n) = a

and compilers are free (obliged?) to represent a value of type Age by an
Int. It might even be rather confusing if foo were not strict, given that
it appears to pattern match on its argument. (Of course, you could 
equally argue that it is confusing that

case Foo undefined of Foo _ -> True = undefined

in a lazy language, but that can't be helped if strict constructors are 
allowed - unless some lexical distinction is introduced, eg strict 
constructor names must start with `!'.)

Why not keep things simple and, as Ryszard Kubiak suggests, abandon the
newtype syntax altogether? 

Sebastian Hunt






Re: Haskell 1.3 (newtype)

1995-09-12 Thread Ryszard Kubiak



In a recent message Phil Wadler argues:

> ...
> Make newtype equivalent to a datatype with one strict constructor.
> Smaller language, more equivalences, simpler semantics, simpler
> implementation.  An all around win!

I strongly agree with Phil and suggest that because of the equivalences
the extra syntax for 'newtype' is simply omitted. It doesn't make sense
to have syntax with so little semantic significance.

Regards, Rysiek





Re: Haskell 1.3 (newtype)

1995-09-12 Thread wadler


Simon offers a compelling reason to make newtype distinct from a strict
datatype with one constructor.  And a semantics to boot!  I withdraw my
objection.   -- P

PS.  The informal explanation might be modified to explain why
newtype must be distinct from a strict datatype.

strict datatype

case Foo undefined of Foo _ -> True  =  undefined

newtype

case Foo undefined of Foo _ -> True  =  True

The latter must be the right thing to do (as pointed out by Simon)
because removing Foo should not change the meaning:

case undefined of _ -> True  =  True

Cheers,  -- P






Re: Haskell 1.3 (newtype)

1995-09-12 Thread Simon L Peyton Jones



Phil writes:


| By the way, with `newtype', what is the intended meaning of
| 
|   case undefined of Foo _ -> True ?
| 
| I cannot tell from the summary on the WWW page.  Defining `newtype'
| in terms of `datatype' and strictness avoids any ambiguity here.
| 
| Make newtype equivalent to a datatype with one strict constructor.
| Smaller language, more equivalences, simpler semantics, simpler
| implementation.  An all around win!

I believe it would be a mistake to do this!  Consider:

newtype Age = Age Int

foo :: Age -> (Int, Age)
foo (Age n) = (n, Age (n+1))

Now, we intend that a value of type (Age Int) should be represented by
an Int.  Thus, apart from the types involved, the following program should
be equivalent:

type Age' = Int

foo' :: Age' -> (Int, Age')
foo' n = (n, n+1)

So is foo' strict in n? No, it isn't.  What about foo?  If newtype is just a
strict data constructor, then it *is* strict in n.

Here's what I wrote a little while ago:

"This all very well, but it needs a more formal treatment.  As it happens, I
don't think it's difficult.  In the rules for case expressions (Fig 3 & 4 in
the 1.2 report) we need to say that the *dynamic* semantics of

case e of { K v -> e1; _ -> e2 }
is
let v = e in e1

if K is the constructor of a "newtype" declaration.
(Of course this translation breaks the static semantics.)

Similarly, the dynamic semantics of (K e) is just that of "e", if
K is the constructor of a "newtype" decl."

Does that make the semantics clear, Phil?

Simon






Re: Haskell 1.3 (newtype)

1995-09-12 Thread wadler


The design of newtype appears to me incorrect.

The WWW page says that declaring

newtype Foo = Foo Int

is distinct from declaring

data Foo = Foo !Int

(where ! is a strictness annotation) because the former gives

case Foo undefined of Foo _ -> True  =  True

and the latter gives

case Foo undefined of Foo _ -> True  =  undefined.


Now, on the face of it, the former behaviour may seem preferable.  But
trying to write a denotational semantics is a good way to get at the
heart of the matter, and the only way I can see to give a denotational
semantics to the former is to make `newtype' define a LIFTED type, and
then to use irrefutable pattern matching.  This seems positively weird,
because the whole point of `newtype' is that it should be the SAME as
the underlying type.

By the way, with `newtype', what is the intended meaning of

case undefined of Foo _ -> True ?

I cannot tell from the summary on the WWW page.  Defining `newtype'
in terms of `datatype' and strictness avoids any ambiguity here.

Make newtype equivalent to a datatype with one strict constructor.
Smaller language, more equivalences, simpler semantics, simpler
implementation.  An all around win!

Cheers,  -- P










Re: Haskell 1.3 (lifted vs unlifted)

1995-09-12 Thread wadler


To the Haskell 1.3 committee,

Two choices in the design of Haskell are:
Should products be lifted?
Should functions be lifted?
Currently, the answer to the first is yes, and to the second is no.
This is ad hoc in the extreme, and I am severely embarrassed that I did
not recognise this more clearly at the time we first designed Haskell.

Dear committee, I urge you, don't repeat our earlier mistakes!  John
Hughes makes a compelling case for yes; and mathematical cleanliness
makes a compelling case for no.  I slightly lean toward yes. (John is a
persuasive individual!)  But unless someone presents a clear and clean
argument for answering the two questions differently, please answer
them consistently.

If both questions are answered yes, then there is a choice as to
whether or not to have a Data class.  Indeed, there are two choices:
Should polymorphic uses of seq be marked by class Data?
Should polymorphic uses of recursion be marked by class Rec?
John Launchbury and Ross Paterson have written a beautiful paper urging
yes on the latter point; ask them for a copy.  Here, I have a mild
preference to answer both questions no, as I think the extra
complication is not worthwhile.  But again, please answer them
consistently.

Cheers,  -- P





Re: Haskell 1.3

1995-09-11 Thread John Hughes




Let me make one more attempt to persuade the committee to change the way
strictness annotations are to be introduced.

First of all, let's recognise that strictness annotations and the seq
function are of enormous importance; this is a vital extension to the
language, not a small detail. Space debugging consists to quite a large
extent of placing applications of seq correctly, and we all know what
dramatic effects space debugging has been able to achieve. The strictness
features are going to be very heavily used in the future.

Recording uses of polymorphic strictness annotations using class Data has
both advantages and disadvantages. A big disadvantage is that curing a space
bug may change the types of many functions in many modules, which at the
least may require a lot of recompilation. The programmer who likes to state
the type of each function will be especially hard hit, of course, which will
unfortunately discourage such a style. But class Data seems to be vital for
cheap deforestation, which is such an important optimisation as to outweigh
the disadvantages.

However, it is an independent question whether or not strictness annotations
should be applicable to function types. And this is where I disagree with
the committee. To quote `Introducing Haskell 1.3',

Every data type, except ->, is a member of the Data class.

In other words, in Haskell 1.3

FUNCTIONS ARE NOT FIRST-CLASS CITIZENS

To design a functional language today, in which this is true, is in my view
deeply mistaken. In the past, I've argued that it will be very frustrating
for those programmers who do discover they need to apply seq to a function
in order to cure a space bug, to find that they are unable to do so. Even
more seriously, programmers weighing up a choice of representation for an
abstract datatype, choosing between a representation as a function or as a
`Data' type, will know that if they choose the function then problems with
space debugging may lurk in the future. Excluding (->) from class Data is a
step away from true `functional' programming towards a style in which
higher-order functions are just a kind of macro.

I see a very great cost in such a philosophical change, and I do not see
that the arguments against strictly evaluating function values are so very
compelling. 

  Implementation difficulties? hbc has provided it for years, and
  even under the STG machine is the problem so very much harder than handling
  shared partial applications correctly? 

  Semantic difficulties? The semantics of lifted function spaces are 
  perfectly well defined. OK, so it's not the exponential of a CCC --- but 
  Haskell's tuples aren't the product either, and I note the proposal to 
  change that has fallen by the wayside. 

  Weaker strictness analysis? I'd like to hear the effect quantified. How
  much slower will Haskell 1.3 run if function spaces are lifted in the
  semantics? Will it be measurable? I'm prepared to pay a few percent.

So here's my proposal: change `Introducing Haskell 1.3' to read

Every data type, including ->, is a member of the Data class.

John Hughes





Re: Haskell 1.3

1995-09-11 Thread John Launchbury


I would like to respond to John's note. My response is largely positive,
though I disagree with a couple of points.

>However, it is an independent question whether or not strictness annotations
>should be applicable to function types. And this is where I disagree with
>the committee. To quote `Introducing Haskell 1.3',
>
>Every data type, except ->, is a member of the Data class.
>
>In other words, in Haskell 1.3
>
>FUNCTIONS ARE NOT FIRST-CLASS CITIZENS

I cannot agree here. Functions are not members of the equality class either,
but that does not demote them to second class citizens. However, John may be
right in suggesting that people will become more reluctant to use functions
as values if they cannot force their evaluation.

>I see a very great cost in such a philosophical change, and I do not see
>that the arguments against strictly evaluating function values are so very
>compelling.
>
>  Implementation difficulties? hbc has provided it for years, and
>  even under the STG machine is the problem so very much harder than handling
>  shared partial applications correctly?

I haven't checked hbc, but I would be interested if someone would confirm
that function strictify works properly. It didn't use to in LML.

>  Semantic difficulties? The semantics of lifted function spaces are
>  perfectly well defined. OK, so it's not the exponential of a CCC --- but
>  Haskell's tuples aren't the product either, and I note the proposal to
>  change that has fallen by the wayside.

This is probably an important point. I see there being value in two sorts
of functions: lifted and non-lifted (or equivalently boxed and unboxed).
A lifted function may be expressed as a computation which delivers a function,
just like lifted integers are computations which deliver integers. Under this
view it would be entirely in keeping with the rest of Haskell for the standard
functions to be lifted, and to leave open the possibility in the future of
introducing unlifted functions.

>So here's my proposal: change `Introducing Haskell 1.3' to read
>
>Every data type, including ->, is a member of the Data class.

I am inclined to agree. Is there a problem then that every type is in Data?
Not at all. The Data class indicates that forcing has been used in the
body of an expression. This is valuable information that is exposed in
the type.

John.







Re: Haskell 1.3 Draft Report

1995-05-19 Thread David Bakin


Hi.  For the TeX-impaired, is there any chance of sticking postscript files
on an ftp site?  Thanks!  -- Dave

>A draft of the Haskell 1.3 report is available by FTP from
>ftp.dcs.glasgow.ac.uk [130.209.240.50] in
>
>   pub/haskell/report/draft-report-1.3.dvi.gz  [Report]
>   pub/haskell/report/draft-libraries-1.3.dvi.gz   [Libraries]
>
>Highlights include:
>
>   Monadic I/O
>   A split into prelude and libraries, with qualified names
>   Strict data types
>   Some minor syntactic revisions
>
>We are planning to revise this and release it in time for FPCA '95.
>There will definitely be additional prelude and library changes;
>including several new libraries.
>
>Feedback is welcome and will be taken into account when revising the
>report, but please remember that we will be very busy over the next few
>weeks (I am also away for the next two weeks!).  Please mail typos., minor
>notes on syntax etc. to me; substantive comments should be sent to
>[EMAIL PROTECTED]
>
>Regards,
>Kevin
>
>
>

--
Dave Bakin  How much work would a work flow flow if a  #include
510-922-5678work flow could flow work?







Re: Haskell 1.3

1993-11-23 Thread kh


Ian Holyer writes:
> To go back to the debate on instances, here is a concrete proposal for 
> handling instances in Haskell 1.3:

I can see what you're doing, but I dislike the idea of no longer being
able to define instances local to a module.  This limits my choice of
class and type names, and may cause problems when importing libraries
defined by other users.  For global (exported) instances your rules
make sense (a variant of these was considered at one point) with the
caveats marked below.
 
>   1) A C-T instance can be defined in any module in which C and T are 
>  in scope.

Fine, in conjunction with 5 and 2 or similar constraints.
 
>   2) A C-T instance defined in module M is in scope in every module which
>  imports from M, directly or indirectly.  (If C or T are not in scope, a
>  module just passes the instance on in its interface).

You need to ignore local C-T instances (i.e. those where a class C or
type T is defined locally and not exported), otherwise mayhem could
result.  Local instances will now also cause problems if there is a
global C-T instance defined in any importing module.

The interface is problematic if a new class with local name C or type
with local type T is defined (or both!), especially if there is a
(local) C-T instance.  Getting round this would involve being much more
explicit about global names in interface files (e.g. an M1.C-M2.T
instance).  There is also potential name capture of type, class, or
operator names by the importing module, which would require 
additional checking of interfaces import (something we would like to 
avoid for efficiency reasons).

>   3) A C-T instance may be imported more than once via different routes,
>  provided that the module of origin is the same.

This implies annotating instances with their module of origin, as
you note below.
 
>   4) If an application of an overloaded function is resolved locally, the
>  relevant instance must be in scope.

...a relevant instance must be in scope...
   ^

>   5) There must be at most one C-T instance defined in the collection of
>  modules which make up any one program (global resolution occurs in Main).

There should be at most one global C-T instance defined (otherwise you
lose the ability to create local types with instances)...  You also
shouldn't specify where resolution takes place.  Link resolution is
much faster...

> I would like to see the origin of instances in interface files.  My preference
> from an implementers point of view would be something like:
> 
>interface M1 whereinterface M3 where
>import M2 (C(..))or   import M2 (C(..))
>import M3 (T(..),fT)  type T = ...
>instance C T where f = fT instance C T where f = fT
> 
> The name fT is invented while compiling M3 and passed around in interface
> files, but not exported from them into implementation modules.  As well as
> specifying the origin of the instance, it gives the code generator something
> to link to. 

This really isn't a problem for an implementation.  We can always link to a
hidden name derived from the unique C-T combination.  Introducing magic
names in an interface sounds like a *very bad* idea -- you might well 
accidentally capture a user- or Prelude-defined name.  For example,

class From where
from :: Int -> [a] -> a

instance From Int where
from = ...

introduces fromInt in the interface, which will clash with the Prelude
name.

  interface M1 where
  import M2(C(...))
  import M3(T(...))
  import M4(instance M2.C M3.T)

is probably closer to what's required.

Regards,
Kevin





Re: Haskell 1.3 [instances]

1993-11-11 Thread Will Partain


   Ian Holyer writes:

   The current restriction that instances must be defined either in
   the class module or the type module is painful.

LISTEN TO THIS MAN!  Trying to use the module system in (what we
imagined to be) a sensible way on the Glasgow Haskell compiler [which
is written in Haskell] has been a nightmare.  Take a pile of
mutually-dependent modules, add the "instance virus" [instances go
with the class or type, and you can't stop them...], and you have
semi-chaos.  All attempts to have export/import lists that "show
what's going on" have been undermined by having to add piles of cruft
to keep instancery happy.

I would go for either of the following not-thought-through choices:

* Instances travel with the *type*, not the class.  99% of the time,
  this is what we want.  If your instance isn't going, add an explicit
  export of the type constructor.  Possibly have a special case for
  instances of user-defined classes for Prelude types...

* Make it so that imported instances whose class/type is out-of-scope
  may be silently ignored (i.e., an exception to the closure rule).

  For example, if I write "import Foo" and Foo's interface includes
  "instance Wibble Wobble" and none of my "imports" happen to bring
  "Wibble" (or "Wobble") into scope, then a compiler may drop this
  instance silently.  It is not an error.  (Of course, if you try to
  *use* such an instance, you will get an error downstream.)

Of course, something that involves new syntax/extra machinery would
also be fine.

Will

PS: Get rid of "default" declarations, too.  No-one uses them. (Hi,
Kevin!)




Re: Haskell 1.3 trivia

1993-10-27 Thread ian


>   How about removing the `where' from `module...where' and
>   `interface...where'   ...
>
> The reason we used the "module...where" convention is to allow for
> multiple modules to be included in one "file".  Your proposal is
> workable, but requires saying something extra about what terminates
> a module.  I agree, however, that having to write "where" all the
> time is a pain (I still forget to put it in sometimes!), so perhaps
> you could complete the proposal with the wording required to say when
> a module ends.

I suggest:

*) remove the paragraph about top-level indenting from 1.5
*) change 5.2:

   script  ->  module1 module2 ...   (n>=1)
   module  ->  { [header ; body] [;] } | { header[;] } | { body[;] }
   header  ->  { [moddecl ; impfix] [;] } | { moddecl[;] } | { impfix[;] }
   impfix  ->  { [impdecls ; fixdecls] [;]} | { impdecls[;] } | { fixdecls[;] }
   moddecl ->  `module' modid [exports]
   body->  topdecls

   NB The form { ... [[fixdecls ;] topdecls [;]] } in the current syntax is
   inconsistent in disallowing {;} which other blocks in the syntax allow.

*) change the text of 5.2 to correspond, and in particular change the second
   paragraph to:

   If the first lexeme in a module is not a {, then the layout rule applies
   for the top level of the module.  Several modules may appear in one script.
   Each module ends when the `module' keyword of the next is encountered.  An
   abbreviated form of module is permitted, which omits the moddecl.  If this
   is used, the moddecl is assumed to be `module Main'.  An abbreviated module
   may not appear in the same script as some unabbreviated modules.

   NB The first paragraph of 5.2 *already* uses the term body for the topdecls
   alone, in contradiction to the current syntax.

*) do the same for interfaces in 5.3 (we don't want modules and interfaces in
   the same file, do we?) and change B.4, B.5, B.6 to match.

Ian




Re: Haskell 1.3 trivia

1993-10-27 Thread hudak-paul


  How about removing the `where' from `module...where' and
  `interface...where' so that these become ordinary topdecls like
  the rest.  This would mean that the convention about topdecls
  not having to be indented would no longer be an ugly exception,
  it would be more consistent with implicit main programs which
  have no introductory `where', and it would be more consistent
  with the fact that the natural break between the header and body
  of a module comes after the fixity decls.
  

The reason we used the "module...where" convention is to allow for
multiple modules to be included in one "file".  Your proposal is
workable, but requires saying something extra about what terminates
a module.  I agree, however, that having to write "where" all the
time is a pain (I still forget to put it in sometimes!), so perhaps
you could complete the proposal with the wording required to say when
a module ends.

-Paul

---
Professor Paul Hudak
Department of Computer Science
Yale University
P.O. Box 208285
New Haven, CT 06520-8285
(203) 432-4715
[EMAIL PROTECTED]





Re: Haskell 1.3 (n+k patterns)

1993-10-12 Thread Lennart Augustsson



jl writes:
> I feel the need to be inflamatory:
> 
>   I believe n+k should go.
Again, I agree completely.  Let's get rid of this horrible wart
once and for all.  It's a special case that makes the language
more difficult to explain and implement.  I've hardly seen any
programs using it so I don't think backwards compat is a problem.
Anyone who thinks this change will cause them more than 10
minutes work, plese speak up.

-- Lennart