Re: [Haskell] Swapping parameters and type classes

2007-09-18 Thread Ian Lynagh
On Tue, Sep 18, 2007 at 03:48:06PM +0100, Andrzej Jaworski wrote:
> Responding to Simon Peyton-Jones'  reminder that this is a low-bandwidth list 
> I
> was obscure and commited a blunder.
> 
> This one and many other threads here are started undoubtedly by experts [sorry
> guys:-)] and coffee brake should work for them, but on numerous occasions
> threads here spawn beginner type questions. So, my thinking was that it is
> perhaps against the tide trying to stop them.
> Why not to make the list Haskell a first contact general practitioner? Then
> creating e.g. "Announcements & Challenge" or "Announcements & ask guru" list
> could take the best from "Haskell" but also would make it less front line and
> thus more elitist, which should imply the manner by itself.

I proposed renaming
haskell@ -> haskell-announce@
haskell-cafe@ -> haskell@
in http://www.haskell.org/pipermail/haskell-cafe/2007-July/028719.html
but the only reply was
There are very few inappropriate posts to the haskell@ list.
I very much doubt that the list names are a problem.
in http://www.haskell.org/pipermail/haskell-cafe/2007-July/028727.html
so I dropped it.

I've just quickly categorised the haskell@ posts from August to see what
the numbers are really like. The posts I've marked "off-topic" are ones
that, as far as I can see, are no more suited to haskell@ than most of
the messages that are sent to [EMAIL PROTECTED] Other peoples'
categorisations might vary, but I'd be surprised if they did
significantly.

http://urchin.earth.li/~ian/haskell-list-categorisation.txt

Of 68 messages, 52 were off-topic and 16 were on-topic, so about a 75-25
split. 5 of the off-topic messages were replies to on-topic messages, so
would probably have been off-topic regardless of the list name unless we
set the haskell-announce@ reply-to address to be haskell@ or moderated
[EMAIL PROTECTED]

Of 28 threads, 13 were entirely off-topic while 15 were at least partly
on-topic, so about a 50-50 split. This is a much better ratio as it is
the chattier threads that tend to be off-topic, of course. There was
only 1 on-topic message that wasn't the start of a thread.

In response to
I very much doubt that the list names are a problem.
I fully understand why someone new to the community, and thus unfamiliar
with the lists' intended purposes, posted
http://www.haskell.org/pipermail/haskell/2007-August/019746.html
to a list called haskell@, but I'm sure they wouldn't have posted it to
[EMAIL PROTECTED]

Something I noticed is that, of the 15 on-topic threads, 9 (including
"The Monad.Reader") were things like calls for papers and conference
announcements, which have a largely different audience than new-library
announcements. Maybe there's even an argument for splitting
haskell-announce in two? haskell-academic-announce?

> You could always
> cross-post but subscribe or answer to one.

Cross-posting to mailing lists doesn't work well, and there's really no
reason for haskell-cafe@ subscribers not to be subscribed to haskell@,
so you might as well only post to haskell@ if you think it should be
crossposted.


Thanks
Ian

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


Re: [Haskell] Swapping parameters and type classes

2007-09-18 Thread Andrzej Jaworski
Responding to Simon Peyton-Jones'  reminder that this is a low-bandwidth list I
was obscure and commited a blunder.

This one and many other threads here are started undoubtedly by experts [sorry
guys:-)] and coffee brake should work for them, but on numerous occasions
threads here spawn beginner type questions. So, my thinking was that it is
perhaps against the tide trying to stop them.
Why not to make the list Haskell a first contact general practitioner? Then
creating e.g. "Announcements & Challenge" or "Announcements & ask guru" list
could take the best from "Haskell" but also would make it less front line and
thus more elitist, which should imply the manner by itself. You could always
cross-post but subscribe or answer to one.

Cheers,
-A.J.

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


[Haskell] Swapping parameters and type classes

2007-09-18 Thread Andrzej Jaworski
Well, the corridors are better known for the men in power:-)
Why don't leave this entry as Reception for the uninitiated and move on to
Announcements and ... Curiosity?

Regards,
-A.J.

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


RE: [Haskell] Swapping parameters and type classes

2007-09-17 Thread Simon Peyton-Jones
This thread is certainly interesting, but it would be better on [EMAIL 
PROTECTED]  The Haskell@haskell.org list is intended as a low-bandwidth list 
for announcements and the like.  Thanks!

Simon

| -Original Message-
| From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED]
| On Behalf Of Bas van Dijk
| Sent: 17 September 2007 20:17
| To: Mads Lindstrøm
| Cc: haskell@haskell.org
| Subject: Re: [Haskell] Swapping parameters and type classes
|
| On 9/17/07, Mads Lindstrøm <[EMAIL PROTECTED]> wrote:
| > Hi Bas
| >
| > Thank you for the answer.
| >
| > I tried to "fill in some blanks" in the example you gave. And mostly
| got
| > a lot of context reduction stack overflows :(
| >
| > Here is my example (a little closer to what I actually need):
| >
| > data Foo a b = Foo { first :: a, second :: b }
| >
| > class Bar (x :: * -> *) where
| > foo :: x a -> a
| >
| > instance Bar (Foo a) where
| > foo x = second x
| >
| > type family BarB a b :: * -> *
| > type instance BarB a b = Foo b
| >
| > instance Bar (BarB a b) where
| > foo x = second x -- this unexpectedly works!
| > --  foo x = first x  -- This unexpectedly gives context reduction
| stack overflow
| >
| > What surprises me is that I still need to look at `second`, even
| though
| > I use BarB. I thought I was swapping the parameters. Whats more
| changing
| > the line:
| >
| > type instance BarB a b = Foo b
| >
| > to
| >
| > type instance BarB a b = Foo a  -- the last letter changed
| >
| > has no effect.
| >
| >
| > Greetings,
| >
| > Mads Lindstrøm
| >
| > P.s. Why can we not just have the option of being explicit about
| which type parameters are applied? Something like:
| >
| > "instance Bar (apply a. Foo a b)" which would apply a and be
| identical to "instance Bar (Foo a)"
| > "instance Bar (apply b. Foo a b)" which would apply b and be what I
| am trying to achieve.
| >
| > It would seem a lot more natural to me. But maybe there are other
| reasons why type families are a better solution?
| >
| > I do not know if I use the right terminology when saying "apply".
| Please correct if there is more correct terms.
| >
| >
| > Bas van Dijk:
| > > On 9/16/07, Mads Lindstrøm <[EMAIL PROTECTED]> wrote:
| > > > But what if I want to "apply" the 'b' ? How do I do that ?
| > >
| > > The following uses type families (functions) and compiles under GHC
| HEAD:
| > >
| > > {-# OPTIONS_GHC -XTypeFamilies -XEmptyDataDecls -
| XTypeSynonymInstances #-}
| > >
| > > data Foo a b
| > >
| > > class Bar (x :: * -> *)
| > >
| > > instance Bar (Foo a)
| > >
| > > type family BarB a b :: * -> *
| > > type instance BarB a b = Foo b
| > >
| > > instance Bar (BarB a b)
| > >
| > >
| > > regards,
| > >
| > > Bas van Dijk
| >
| >
|
| Mads, my sollution was not correct.
|
| This is why:
|
| instance Bar (BarB a b)
|
| is equal to:
|
| instance Bar (Foo b)
|
| which is just equal to:
|
| instance Bar (Foo a)
|
| The 'b' in  'instance Bar (Foo b)' has nothing to do with the 'b' in
| 'Foo a b'. In fact the 'b' in 'BarB a b' is equal to the 'a' in 'Foo a
| b'.
|
| Sorry that I bothered you with this but like I said, it was late and I
| already consumed some wine. Not a good combination when programming
| ;-)
|
| Bas.
| ___
| Haskell mailing list
| Haskell@haskell.org
| http://www.haskell.org/mailman/listinfo/haskell
___
Haskell mailing list
Haskell@haskell.org
http://www.haskell.org/mailman/listinfo/haskell


Re: [Haskell] Swapping parameters and type classes

2007-09-17 Thread Bas van Dijk
On 9/17/07, Mads Lindstrøm <[EMAIL PROTECTED]> wrote:
> Hi Bas
>
> Thank you for the answer.
>
> I tried to "fill in some blanks" in the example you gave. And mostly got
> a lot of context reduction stack overflows :(
>
> Here is my example (a little closer to what I actually need):
>
> data Foo a b = Foo { first :: a, second :: b }
>
> class Bar (x :: * -> *) where
> foo :: x a -> a
>
> instance Bar (Foo a) where
> foo x = second x
>
> type family BarB a b :: * -> *
> type instance BarB a b = Foo b
>
> instance Bar (BarB a b) where
> foo x = second x -- this unexpectedly works!
> --  foo x = first x  -- This unexpectedly gives context reduction stack 
> overflow
>
> What surprises me is that I still need to look at `second`, even though
> I use BarB. I thought I was swapping the parameters. Whats more changing
> the line:
>
> type instance BarB a b = Foo b
>
> to
>
> type instance BarB a b = Foo a  -- the last letter changed
>
> has no effect.
>
>
> Greetings,
>
> Mads Lindstrøm
>
> P.s. Why can we not just have the option of being explicit about which type 
> parameters are applied? Something like:
>
> "instance Bar (apply a. Foo a b)" which would apply a and be identical to 
> "instance Bar (Foo a)"
> "instance Bar (apply b. Foo a b)" which would apply b and be what I am trying 
> to achieve.
>
> It would seem a lot more natural to me. But maybe there are other reasons why 
> type families are a better solution?
>
> I do not know if I use the right terminology when saying "apply". Please 
> correct if there is more correct terms.
>
>
> Bas van Dijk:
> > On 9/16/07, Mads Lindstrøm <[EMAIL PROTECTED]> wrote:
> > > But what if I want to "apply" the 'b' ? How do I do that ?
> >
> > The following uses type families (functions) and compiles under GHC HEAD:
> >
> > {-# OPTIONS_GHC -XTypeFamilies -XEmptyDataDecls -XTypeSynonymInstances #-}
> >
> > data Foo a b
> >
> > class Bar (x :: * -> *)
> >
> > instance Bar (Foo a)
> >
> > type family BarB a b :: * -> *
> > type instance BarB a b = Foo b
> >
> > instance Bar (BarB a b)
> >
> >
> > regards,
> >
> > Bas van Dijk
>
>

Mads, my sollution was not correct.

This is why:

instance Bar (BarB a b)

is equal to:

instance Bar (Foo b)

which is just equal to:

instance Bar (Foo a)

The 'b' in  'instance Bar (Foo b)' has nothing to do with the 'b' in
'Foo a b'. In fact the 'b' in 'BarB a b' is equal to the 'a' in 'Foo a
b'.

Sorry that I bothered you with this but like I said, it was late and I
already consumed some wine. Not a good combination when programming
;-)

Bas.
___
Haskell mailing list
Haskell@haskell.org
http://www.haskell.org/mailman/listinfo/haskell


Re: [Haskell] Swapping parameters and type classes

2007-09-17 Thread Mads Lindstrøm
Hi Bas

Thank you for the answer.

I tried to "fill in some blanks" in the example you gave. And mostly got
a lot of context reduction stack overflows :(

Here is my example (a little closer to what I actually need):

data Foo a b = Foo { first :: a, second :: b }

class Bar (x :: * -> *) where
foo :: x a -> a

instance Bar (Foo a) where
foo x = second x

type family BarB a b :: * -> *
type instance BarB a b = Foo b

instance Bar (BarB a b) where
foo x = second x -- this unexpectedly works! 
--  foo x = first x  -- This unexpectedly gives context reduction stack 
overflow

What surprises me is that I still need to look at `second`, even though
I use BarB. I thought I was swapping the parameters. Whats more changing
the line:

type instance BarB a b = Foo b

to

type instance BarB a b = Foo a  -- the last letter changed

has no effect.


Greetings,

Mads Lindstrøm

P.s. Why can we not just have the option of being explicit about which type 
parameters are applied? Something like:

"instance Bar (apply a. Foo a b)" which would apply a and be identical to 
"instance Bar (Foo a)"
"instance Bar (apply b. Foo a b)" which would apply b and be what I am trying 
to achieve.

It would seem a lot more natural to me. But maybe there are other reasons why 
type families are a better solution?

I do not know if I use the right terminology when saying "apply". Please 
correct if there is more correct terms.


Bas van Dijk:
> On 9/16/07, Mads Lindstrøm <[EMAIL PROTECTED]> wrote:
> > But what if I want to "apply" the 'b' ? How do I do that ?
> 
> The following uses type families (functions) and compiles under GHC HEAD:
> 
> {-# OPTIONS_GHC -XTypeFamilies -XEmptyDataDecls -XTypeSynonymInstances #-}
> 
> data Foo a b
> 
> class Bar (x :: * -> *)
> 
> instance Bar (Foo a)
> 
> type family BarB a b :: * -> *
> type instance BarB a b = Foo b
> 
> instance Bar (BarB a b)
> 
> 
> regards,
> 
> Bas van Dijk

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


Re: [Haskell] Swapping parameters and type classes

2007-09-17 Thread Ian Lynagh
On Sun, Sep 16, 2007 at 01:59:02PM -0700, Stefan O'Rear wrote:
> > 
> > {-# OPTIONS_GHC -XTypeFamilies -XEmptyDataDecls -XTypeSynonymInstances #-}
> 
> {-# LANGUAGE TypeFamilies, EmptyDataDecls, TypeSynonymInstances #-}
> 
> (Ian/Simon: I've seen this several times now.  Maybe there should be a
> warning for -X in OPTIONS?  Is that even feasable?)

Currently we can't even give a warning when completely deprecated flags
are used, but when fixing that I think we should also do as you suggest.


Thanks
Ian

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


Re: [Haskell] Swapping parameters and type classes

2007-09-16 Thread Stefan O'Rear
On Sun, Sep 16, 2007 at 10:45:39PM +0200, Bas van Dijk wrote:
> On 9/16/07, Mads Lindstrøm <[EMAIL PROTECTED]> wrote:
> > But what if I want to "apply" the 'b' ? How do I do that ?
> 
> The following uses type families (functions) and compiles under GHC HEAD:
> 
> {-# OPTIONS_GHC -XTypeFamilies -XEmptyDataDecls -XTypeSynonymInstances #-}

Eek!

That should be:

{-# LANGUAGE TypeFamilies, EmptyDataDecls, TypeSynonymInstances #-}

Modulo the fact that only GHC support type families at the moment, the
latter will be portable...

(Ian/Simon: I've seen this several times now.  Maybe there should be a
warning for -X in OPTIONS?  Is that even feasable?)

Stefan


signature.asc
Description: Digital signature
___
Haskell mailing list
Haskell@haskell.org
http://www.haskell.org/mailman/listinfo/haskell


Re: [Haskell] Swapping parameters and type classes

2007-09-16 Thread Bas van Dijk
On 9/16/07, Bas van Dijk <[EMAIL PROTECTED]> wrote:
> The following uses type families (functions) and compiles under GHC HEAD:
> ...

Oops this is not correct! Its getting late... oh well

Bas
___
Haskell mailing list
Haskell@haskell.org
http://www.haskell.org/mailman/listinfo/haskell


Re: [Haskell] Swapping parameters and type classes

2007-09-16 Thread Bas van Dijk
On 9/16/07, Mads Lindstrøm <[EMAIL PROTECTED]> wrote:
> But what if I want to "apply" the 'b' ? How do I do that ?

The following uses type families (functions) and compiles under GHC HEAD:

{-# OPTIONS_GHC -XTypeFamilies -XEmptyDataDecls -XTypeSynonymInstances #-}

data Foo a b

class Bar (x :: * -> *)

instance Bar (Foo a)

type family BarB a b :: * -> *
type instance BarB a b = Foo b

instance Bar (BarB a b)


regards,

Bas van Dijk
___
Haskell mailing list
Haskell@haskell.org
http://www.haskell.org/mailman/listinfo/haskell


Re: [Haskell] Swapping parameters and type classes

2007-09-16 Thread Brent Yorgey
On 9/16/07, Mads Lindstrøm <[EMAIL PROTECTED]> wrote:
>
> Hi all
>
> If I have this type:
>
>   data Foo a b = ...
>
> and this class
>
>   class Bar (x :: * -> *) where ...
>
> I can imagine two ways to make Foo an instance of Bar. Either I must
> "apply" the 'a' or the 'b' in (Foo a b). Otherwise it will not have the
> right kind. To "apply" the 'a' I can do:
>
>   instance Bar (Foo a) where ...
>
> But what if I want to "apply" the 'b' ? How do I do that ?


One easy way would be to create a newtype with the type parameters swapped:

  newtype Oof b a = Oof (Foo a b)
  instance Bar (Oof b) where ...

Of course, if you want to partially apply the second parameter of a
function, you use 'flip'.  I thought for a while about whether there's some
sort of typeclass hackery which is directly parallel to the use of 'flip',
but couldn't come up with anything.  Anyone?

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


[Haskell] Swapping parameters and type classes

2007-09-16 Thread Mads Lindstrøm
Hi all

If I have this type:

  data Foo a b = ...

and this class

  class Bar (x :: * -> *) where ...

I can imagine two ways to make Foo an instance of Bar. Either I must
"apply" the 'a' or the 'b' in (Foo a b). Otherwise it will not have the
right kind. To "apply" the 'a' I can do:

  instance Bar (Foo a) where ...

But what if I want to "apply" the 'b' ? How do I do that ?


Greetings,

Mads Lindstrøm


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


Re: [Haskell] Newbie help with type-classes

2007-05-11 Thread Derek Elkins

Ryan Ingram wrote:

[EMAIL PROTECTED] is better for this type of question.  Follow-up is set 
to it.


Here's a test case for the problem I'm having; I'm using runhaskell from 
ghc v6.6.
 
Problem #1) Without -fallow-undecidable-instances, I get the following 
error:

Constraint is no smaller than the instance head

This is bad.


Problem #2) With -fallow-undecidable-instances, I get this error instead:
Overlapping instances for ConvertToIntList ()


I don't understand why there is an overlapping instances error; () is 
not an instance of ConvertToInt so how could that instance ever apply?


I write anywhere, instance ConvertToInt () where ...
Now it is overlapping.

Is there something basic about type-classes that I'm not understanding 
here?  
They are open (Open World Assumption).  I can add a new instance anywhere at any 
time.



Code below:
{-# OPTIONS -fglasgow-exts -fallow-undecidable-instances #-}
 
module TestCase

where
 
class ConvertToInt a where

   conv :: a -> Int
 
class ConvertToIntList a where

   convl :: [a] -> [Int]
 
instance ConvertToInt Int where

   conv = id
 
instance ConvertToInt a => ConvertToIntList a where

This is what it's complaining about in the first error; this doesn't work.


   convl = map conv
 
instance ConvertToIntList () where

   convl x = []

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


Re: [Haskell] Newbie help with type-classes

2007-05-11 Thread Bas van Dijk

Maybe this is not what you want, but you can also put the 'convl'
function in the 'ConvertToInt' class.

class ConvertToInt a where
  conv  :: a -> Int
  convl :: [a] -> [Int]

With this approach you don't need any language extension.

regards,

Bas van Dijk

On 5/11/07, Ryan Ingram <[EMAIL PROTECTED]> wrote:

Here's a test case for the problem I'm having; I'm using runhaskell from ghc
v6.6.

Problem #1) Without -fallow-undecidable-instances, I get the following
error:
Constraint is no smaller than the instance head
  in the constraint: ConvertToInt a
(Use -fallow-undecidable-instances to permit this)
In the instance declaration for `ConvertToIntList a'

Problem #2) With -fallow-undecidable-instances, I get this error instead:
Overlapping instances for ConvertToIntList ()
  arising from use of `convl' at testcase.hs:28:6-15
Matching instances:
  instance (ConvertToInt a) => ConvertToIntList a
 -- Defined at testcase.hs:15:0
  instance ConvertToIntList () -- Defined at testcase.hs:18:0
In the expression: convl [()]
In the definition of `xl2': xl2 = convl [()]

I don't understand why there is an overlapping instances error; () is not an
instance of ConvertToInt so how could that instance ever apply?

Is there something basic about type-classes that I'm not understanding here?
 My actual problem is more complicated than this, but this test-case covers
the basic issue; something being an instance of class A means that I can
derive an instance of class B for it, but I want to implement other
instances of class B as well.

Code below:


{-# OPTIONS -fglasgow-exts -fallow-undecidable-instances #-}

module TestCase
where
 class ConvertToInt a where
   conv :: a -> Int

class ConvertToIntList a where
   convl :: [a] -> [Int]

instance ConvertToInt Int where
   conv = id

instance ConvertToInt a => ConvertToIntList a where
   convl = map conv

instance ConvertToIntList () where
   convl x = []

x :: Int
x = 5

xl :: [Int]
xl = convl [x]

xl2 :: [Int]
xl2 = convl [()]
___
Haskell mailing list
Haskell@haskell.org
http://www.haskell.org/mailman/listinfo/haskell



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


Re: [Haskell] Newbie help with type-classes

2007-05-11 Thread Bas van Dijk

Add: -fallow-overlapping-instances to your OPTIONS pragma and read
about overlapping instances in the GHC User Guide:

http://www.haskell.org/ghc/docs/latest/html/users_guide/type-extensions.html#instance-overlap

regards,

Bas van Dijk

On 5/11/07, Ryan Ingram <[EMAIL PROTECTED]> wrote:

Here's a test case for the problem I'm having; I'm using runhaskell from ghc
v6.6.

Problem #1) Without -fallow-undecidable-instances, I get the following
error:
Constraint is no smaller than the instance head
  in the constraint: ConvertToInt a
(Use -fallow-undecidable-instances to permit this)
In the instance declaration for `ConvertToIntList a'

Problem #2) With -fallow-undecidable-instances, I get this error instead:
Overlapping instances for ConvertToIntList ()
  arising from use of `convl' at testcase.hs:28:6-15
Matching instances:
  instance (ConvertToInt a) => ConvertToIntList a
 -- Defined at testcase.hs:15:0
  instance ConvertToIntList () -- Defined at testcase.hs:18:0
In the expression: convl [()]
In the definition of `xl2': xl2 = convl [()]

I don't understand why there is an overlapping instances error; () is not an
instance of ConvertToInt so how could that instance ever apply?

Is there something basic about type-classes that I'm not understanding here?
 My actual problem is more complicated than this, but this test-case covers
the basic issue; something being an instance of class A means that I can
derive an instance of class B for it, but I want to implement other
instances of class B as well.

Code below:


{-# OPTIONS -fglasgow-exts -fallow-undecidable-instances #-}

module TestCase
where
 class ConvertToInt a where
   conv :: a -> Int

class ConvertToIntList a where
   convl :: [a] -> [Int]

instance ConvertToInt Int where
   conv = id

instance ConvertToInt a => ConvertToIntList a where
   convl = map conv

instance ConvertToIntList () where
   convl x = []

x :: Int
x = 5

xl :: [Int]
xl = convl [x]

xl2 :: [Int]
xl2 = convl [()]
___
Haskell mailing list
Haskell@haskell.org
http://www.haskell.org/mailman/listinfo/haskell



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


[Haskell] Newbie help with type-classes

2007-05-10 Thread Ryan Ingram

Here's a test case for the problem I'm having; I'm using runhaskell from ghc
v6.6.

Problem #1) Without -fallow-undecidable-instances, I get the following
error:
   Constraint is no smaller than the instance head
 in the constraint: ConvertToInt a
   (Use -fallow-undecidable-instances to permit this)
   In the instance declaration for `ConvertToIntList a'
Problem #2) With -fallow-undecidable-instances, I get this error instead:
   Overlapping instances for ConvertToIntList ()
 arising from use of `convl' at testcase.hs:28:6-15
   Matching instances:
 instance (ConvertToInt a) => ConvertToIntList a
-- Defined at testcase.hs:15:0
 instance ConvertToIntList () -- Defined at testcase.hs:18:0
   In the expression: convl [()]
   In the definition of `xl2': xl2 = convl [()]
I don't understand why there is an overlapping instances error; () is not an
instance of ConvertToInt so how could that instance ever apply?

Is there something basic about type-classes that I'm not understanding
here?  My actual problem is more complicated than this, but this test-case
covers the basic issue; something being an instance of class A means that I
can derive an instance of class B for it, but I want to implement other
instances of class B as well.

Code below:
{-# OPTIONS -fglasgow-exts -fallow-undecidable-instances #-}

module TestCase
where

class ConvertToInt a where
  conv :: a -> Int

class ConvertToIntList a where
  convl :: [a] -> [Int]

instance ConvertToInt Int where
  conv = id

instance ConvertToInt a => ConvertToIntList a where
  convl = map conv

instance ConvertToIntList () where
  convl x = []

x :: Int
x = 5

xl :: [Int]
xl = convl [x]

xl2 :: [Int]
xl2 = convl [()]
___
Haskell mailing list
Haskell@haskell.org
http://www.haskell.org/mailman/listinfo/haskell


[Haskell] A question about a possible bug in GHC regarding GADTs and type classes

2007-01-17 Thread Pablo Nogueira

Hi,

I've been told the following short code is correct but it's GHC's
fault it does not type check.
Is that the case?

--
{-# OPTIONS -fglasgow-exts #-}

-- An expression GADT:

data Exp :: * -> * where
 LitNum  :: Num a => a -> Exp a
 LitBool  :: Bool -> Exp Bool
 Plus  :: Num a => Exp a -> Exp a -> Exp a
 And   :: Exp Bool -> Exp Bool -> Exp Bool
 If   :: Exp Bool -> Exp a -> Exp a -> Exp a

-- An expression evaluator:

evalExp :: Exp a -> a
evalExp (LitNum i)  = i
evalExp (LitBool b) = b
evalExp (Plus x y)  = evalExp x + evalExp y
evalExp (And  x y)  = evalExp x && evalExp y
evalExp (If c t e)  = if (evalExp c) then (evalExp t) else (evalExp e)
--

The type checker complains that evalExp needs a Num constraint on its
type signature.
This can't be right, for Bool is not an instance of Num, right?

Is it the case that the interaction between GADTs and type classes is
not fully worked out yet?

Here is a related problem. I'd like to make the types of expressions
extensible by using a type class:
--
class TyRange a
instance TyRange Int
instance TyRange Bool

 data Exp :: * -> * where
   Lit :: TyRange a => a -> Exp a
   Plus :: Exp Int  -> Exp Int  -> Exp Int
   And  :: Exp Bool -> Exp Bool -> Exp Bool
   If   :: TyRange a => Exp Bool -> Exp a -> Exp a -> Exp a

But I cannot add the types in other classes into TyRange in modular
fashion, cause the superclass is specified at the moment of
declaration.

I may try to extend TyRange by adding the instances in, say, Num:

--
{-# OPTIONS -fglasgow-exts #-}
{-# OPTIONS -fallow-undecidable-instances #-}

class TyRange a
instance TyRange Bool
instance Num a => TyRange a

data Exp :: * -> * where
 Lit:: TyRange a => a -> Exp a
 Plus :: Exp Int  -> Exp Int  -> Exp Int
 And  :: Exp Bool -> Exp Bool -> Exp Bool
 If  :: TyRange a => Exp Bool -> Exp a -> Exp a -> Exp a

evalExp :: Exp a -> a
evalExp (Lit i) = i
evalExp (Plus x y)  = evalExp x + evalExp y
evalExp (And  x y)  = evalExp x && evalExp y
evalExp (If c t e)  = if (evalExp c) then (evalExp t) else (evalExp e)
--

But I get the following error when evaluating   evalExp (If (Lit True)
(Lit 1) (Lit 2))

Overlapping instances for TyRange Bool
 arising from use of `Lit' at :1:13-15
   Matching instances:
 /home/pni/Papers/EDT/TyRangeProblem.hs:5:0: instance TyRange Bool
 /home/pni/Papers/EDT/TyRangeProblem.hs:4:0: instance (Num a) => TyRange a
   In the first argument of `If', namely `(Lit True)'
   In the first argument of `evalExp', namely `(If (Lit True) (Lit 1) (Lit 2))

Apologies for being so daft, but why are the instances overlapping if
Bool is not in Num?
___
Haskell mailing list
Haskell@haskell.org
http://www.haskell.org/mailman/listinfo/haskell


[Haskell] Paper announcement: Software Extension and Integration with Type Classes

2006-07-31 Thread Ralf Lammel
Dear Haskellers,

The following paper may still benefit from your comment.
The final version is only due per 10 August 2006.

Thanks,
Ralf Laemmel

--

http://homepages.cwi.nl/~ralf/gpce06/ 

Title: Software Extension and Integration with Type Classes

Authors: Ralf Lämmel and Klaus Ostermann 

Abstract 

The abilities to extend a software module and to integrate a software module 
into an existing software system without changing existing source code are 
fundamental challenges in software engineering and programming-language design. 
We show that these challenges can be tackled, at the level of language 
expressiveness, by using the language concept of type classes, as it is 
available in the functional programming language Haskell. A detailed comparison 
with related work shows that type classes provide a powerful framework in which 
solutions to known software extension and integration problems can be provided. 
We also pinpoint several limitations of type classes in this context. 

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


Low-level notation for type classes WAS: [Haskell] A puzzle and an annoying feature

2004-11-25 Thread Martin Sulzmann
Hi,

Daan said:

 > 
 > Personally, I feel that this problem might be better solved by
 > making a lot of the implicit assumptions (and semantics) of type
 > classes more explicit, and bring them under user control. Of course,
 > I do have not have any idea of how this should be done concretely ;-)
 > 
 > (although type class directives might be a step in the right direction?)
 > 

Well, you might not need to look that far :)
To a great extent you can use Constraint Handling Rules (CHRs)
to explain type classes.

E.g., consider

Gregory J. Duck, Simon Peyton-Jones, Peter J. Stuckey and Martin Sulzmann  
"Sound and Decidable Type Inference for Functional Dependencies"

Peter J. Stuckey and Martin Sulzmann  
"A Theory of Overloading"


I've just skimmed through the "Type Class Directives" paper.
Pl correct me if I'm wrong but it appears that
the disjoint directive can be modeled by CHRs.

Example:

disjoint (Integral, Fractional)

can be encoded by

rule Integral a, Fractional a ==> False (1)

The never directive is in fact a special instance of disjoint.
E.g.,

never Num Bool

can be encoded by

rule Num Bool ==> False (2)

Note that the Chameleon type debugger provides type error explanation
support if the error is due to rule applications such as (1) and (2).

Martin
___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell


Re: [Haskell] Separate Namespaces and Type Classes

2004-07-09 Thread S.M.Kahrs

> one should be able to define two instances having the same signature, as 
> long as they are in different namespaces
[snip]
> But now, ghc complains about two instances of Foo Integer, although 
> there should be none in the namespace main.

It's a Haskell problem, not a ghc one.

Class instances are not constrained by module boundaries.
Other people have found this to be a problem,
e.g. in combination with tools like Strafunski - you just
cannot encapsulate a class instance in a module.

It's a design flaw in Haskell.

> I have not found any documentation on why ghc behaves like this and 
> whether this conforms to the haskell language specification.
> Is there any haskell compiler out there that is able to compile the 
> above example?

I think Clean (a very similar language) permits to limit the scope
of class instances.

Stefan
___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell


Re: [Haskell] Separate Namespaces and Type Classes

2004-07-08 Thread Ketil Malde
Stephan Herhut <[EMAIL PROTECTED]> writes:

> module B(bar) where
> instance Foo Integer where

> module C(tango)
> instance Foo Integer where

> import B(bar)
> import C(tango)

> But now, ghc complains about two instances of Foo Integer, although
> there should be none in the namespace main.

I suspect the problem is that instances are always exported and
imported, so that GHC sees both in Main, and complains.  Perhaps this
could be relaxed to allow your situation (where the class isn't used
directly in Main anyway)?

-kzm
-- 
If I haven't seen further, it is by standing in the footprints of giants
___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell


[Haskell] Separate Namespaces and Type Classes

2004-07-08 Thread Stephan Herhut
Hi all,
I am pretty new to haskell, but while exploring the haskell module 
system, I came along some questions. As far as I found out, haskell 
supports separated namespaces, i.e. every module has its own symbol 
space. Thus, when defining a class in one module like

module A(Foo(f)) where
class Foo a where
 f ::  a -> Integer
one should be able to define two instances having the same signature, as 
long as they are in different namespaces

module B(bar) where
import A(Foo(f))
instance Foo Integer where
 f x = x
bar x = f x
module C(tango)
import A(Foo(f))
instance Foo Integer where
 f x = x + 1
tango x = f x
As the integer instances of Foo are in separate modules and thus 
namespaces, one should be able to just import bar and tango

module Main(main)
import B(bar)
import C(tango)
main = print( (bar 5) + (tango 4) )
But now, ghc complains about two instances of Foo Integer, although 
there should be none in the namespace main.
I have not found any documentation on why ghc behaves like this and 
whether this conforms to the haskell language specification.
Is there any haskell compiler out there that is able to compile the 
above example?

Thanks for your help
Stephan
___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell


Re: [Haskell] generic currying (type classes and functional dependencies)

2004-05-13 Thread Ronny Wichers Schreur
Duncan Coutts writes (to the Haskell Mailing list):

I'm trying to write a generic curry (& uncurry) function that works for
functions of any arity.
See 
where oleg presents a (ghc-specific) solution.
Cheers,

Ronny Wichers Schreur
___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell


Re: [Haskell] generic currying (type classes and functional dependencies)

2004-05-11 Thread Esa Pulkkinen

In message <[EMAIL PROTECTED]>, Duncan Coutts writes:
>I'm trying to write a generic curry (& uncurry) function that works for
>functions of any arity. I have a couple solutions that nearly work, both
>involving type classes.
[SNIP]
>Any insight or suggestions would be interesting.

Here's one solution, which I think is more general than what you ask,
but I guess it should work as well. It's based on adjunctions from
category theory:

class (Functor path, Functor space) =>
Adjunction path space | path -> space, space -> path where
  leftAdjunct :: (path top -> bot) -> top -> space bot
  unit :: top -> space (path top) 
  rightAdjunct :: (top -> space bot) -> path top -> bot
  counit :: path (space bot) -> bot 
  -- minimum required impl: unit xor leftAdjunct
  -- minimum required impl: counit xor rightAdjunct
  unit = leftAdjunct id
  leftAdjunct f = fmap f . unit
  counit = rightAdjunct id
  rightAdjunct g = counit . fmap g

-- Here are some instances for different arities:

instance Adjunction ((,) a) ((->) a) where
 unit t = \arg -> (arg,t)
 counit (x,f) = f x

newtype Func2 a b c = Func2 (a -> b -> c)
   -- Func2 is only needed due to syntax of partial type constructor application

instance Adjunction ((,,) a b) (Func2 a b) where
  unit t = Func2 (\arg1 arg2 -> (arg1,arg2,t))
  counit (arg1,arg2,Func2 f) = f arg1 arg2

instance Functor ((,,) a b) where
  fmap f (x,y,z) = (x,y,f z)

instance Functor (Func2 a b) where
  fmap f (Func2 g) = Func2 (\a b -> f (g a b))

Here, 'leftAdjunct' is a generalization of curry and rightAdjunct is a
generalization of uncurry.
-- 
  Esa Pulkkinen
___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell


Re: [Haskell] generic currying (type classes and functional dependencies)

2004-05-11 Thread Malcolm Wallace
Duncan Coutts <[EMAIL PROTECTED]> writes:

> So I thought that functional dependencies might help because the curried
> type should uniquely determine the uncurried type (and vice versa).
> However if I change the class declaration to:
> 
> class Curry tupled curried | tupled -> curried, curried -> tupled  where
>   genericCurry   :: tupled -> curried
>   genericUncurry :: curried -> tupled
> 
> Then the compiler complains about my instance declarations:
> 
> Functional dependencies conflict between instance declarations:
>   ./Curry.hs:11:0: instance Curry ((a, b) -> c) (a -> b -> c)
>   ./Curry.hs:16:0:
> instance (Curry ((b, c) -> d) (b -> c -> d)) =>
>  Curry ((a, (b, c)) -> d) (a -> b -> c -> d)
> 
> I don't fully understand why this is the case, but it is to do with the
> nested pairing, because individual instance declarations for 3-tuples,
> 4-tuples work fine.

With a little alpha-renaming:

instance Curry ((a, b) -> c) (a -> b -> c)

instance (Curry ((e, f) -> g) (e -> f -> g)) =>
  Curry ((d, (e, f)) -> g) (d -> e -> f -> g)

It should be fairly easy to see that the type
  (d, (e, f)) -> g
is an instance of
  (a, b) -> c
where a==d and b==(e,f) and c==g.  Also
  (d -> e -> f -> g)
is an instance of
  (a -> b -> c)
where a=d and b==e and c==(f->g).  So for one thing your two instances
overlap, but additionally, the type-variables do not unify, because
in the tupled part of the Curry predicate, b==(e,f), but in the curried
part of the predicate, b==e.

Regards,
Malcolm
___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell


[Haskell] generic currying (type classes and functional dependencies)

2004-05-11 Thread Duncan Coutts
Hi All,

I'm trying to write a generic curry (& uncurry) function that works for
functions of any arity. I have a couple solutions that nearly work, both
involving type classes.

Here's the first one:

class Curry tupled curried where
  genericCurry   :: tupled -> curried
  genericUncurry :: curried -> tupled

The base case is obvious:

instance Curry ((a,b) -> c) (a -> b -> c) where
  genericCurry   f   x y  = f (x,y)
  genericUncurry f' (x,y) = f' x y

However, the inductive case is more tricky. We cannot generically create
tuples of arbitrary size so we'll have to make do with left (or right)
nested pairs. This nesting leads to problems later and for starters
requires overlapping instances:

instance Curry (   (b,c)  -> d) ( b -> c -> d) =>
 Curry ((a,(b,c)) -> d) (a -> b -> c -> d) where
  genericCurry   f  a  b c   = f (a,(b,c))
  genericUncurry f (a,(b,c)) = f  a  b c

This works, but when we come to use it we often run into cases where the
type checker complains with messages such as:
No instance for (Curry ((Int, Int) -> Int) (a -> b -> Int))
I guess that this is because it fails to be able to convince itself that
a & b are Int, in which case there would be an instance. This can be
solved by supplying enough type annotations, however this is annoying
and part of the point of a generic curry is that we don't know the arity
of the function to which we are applying it.

So I thought that functional dependencies might help because the curried
type should uniquely determine the uncurried type (and vice versa).
However if I change the class declaration to:

class Curry tupled curried | tupled -> curried, curried -> tupled  where
  genericCurry   :: tupled -> curried
  genericUncurry :: curried -> tupled

Then the compiler complains about my instance declarations:

Functional dependencies conflict between instance declarations:
  ./Curry.hs:11:0: instance Curry ((a, b) -> c) (a -> b -> c)
  ./Curry.hs:16:0:
instance (Curry ((b, c) -> d) (b -> c -> d)) =>
 Curry ((a, (b, c)) -> d) (a -> b -> c -> d)

I don't fully understand why this is the case, but it is to do with the
nested pairing, because individual instance declarations for 3-tuples,
4-tuples work find.

Any insight or suggestions would be interesting.

Duncan

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell


Re: Type classes confusion

2004-01-10 Thread andrew cooke

Ah.  I just need to drop the context from the data type declaration.

Sorry,
Andrew

andrew cooke said:
>
> Hi,
>
> I'm trying to use type classes and suspect I've got confused somewhere
> down the line, because I've got to an error message that I don't
> understand and can't remove.
>
> I have a class that works like a hash table, mapping from String to some
> type.  I have two instances, one that is case insensitive for keys.  I
> want to hide these instances from the rest of the code, which should only
> use the class.  This class is called Dictionary.
>
> In addition, for Dictionaries that map Strings to Strings, I have some
> functions which do substitutions on Strings using their own contents.
> Possibly the first source of problems is that I can't find a way to
> express these two classes together without multiple parameter type classes
> (one parameter for the case/no case and one for the type returned):
>
> class Dictionary d a where
>   add'   :: d a -> (String, a) -> d a
>   ...
>
> instance Dictionary DictNoCase a where
>   add' d (k, v) = ...
>
> -- Dict is the underlying tree implementation and Maybe stores the
> -- value for the null (empty string) key.
> data DictNoCase a = DictNoCase (Dict a) (Maybe a)
>
> class (Dictionary d String) => SubDictionary d where
>   substitute :: d String -> String -> String
>   ...
>
> instance SubDictionary DictNoCase where
>   substitute d s = ...
>
> All the above compiles and seems correct (is it?).
>
> I also provide an empty instance of the two instance types.  For
> DictNoCase, this is
> empty = DictCase Empty Nothing
> where Empty is the empty type constructor for Dict
>
> Now (almost there) elsewhere I want to define a data type that contains
> two of these Dictionaries.  One stores String values.  The other stores
> functions that take this same type and return a result and a copy of the
> type:
>
> data Context s f = (Dictionary s String, Dictionary f (CustomFn s f)) =>
> Ctx {state :: s String,
>  funcs :: f (CustomFn s f)}
>
> type CustomFn s f = Context s f -> Arg -> IO (Context s f, Result s f)
>
> data Result s f = Attr Name String
> | Repeat (CustomFn s f)
> ...
>
> newContext = Ctx empty emptyNC
>
> (where empty is the case-sensitive empty dictionary)
>
> Now THAT doesn't compile:
>
> Template.lhs:60:
> All of the type variables in the constraint `Dictionary s
> String' are
> already
> in scope
> (at least one must be universally quantified here)
> When checking the existential context of constructor `Ctx'
> In the data type declaration for `Context'
>
> Template.lhs:60:
> All of the type variables in the constraint `Dictionary f
> (CustomFn s
> f)' are
> already in scope
> (at least one must be universally quantified here)
> When checking the existential context of constructor `Ctx'
> In the data type declaration for `Context'
>
> where line 60 is "data Context"
>
> And I can't see what I've done wrong.  Any help gratefully received.
>
> Cheers,
> Andrew
>
> --
> personal web site: http://www.acooke.org/andrew
> personal mail list: http://www.acooke.org/andrew/compute.html
> ___
> Haskell mailing list
> [EMAIL PROTECTED]
> http://www.haskell.org/mailman/listinfo/haskell
>
>


-- 
personal web site: http://www.acooke.org/andrew
personal mail list: http://www.acooke.org/andrew/compute.html
___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell


Type classes confusion

2004-01-10 Thread andrew cooke

Hi,

I'm trying to use type classes and suspect I've got confused somewhere
down the line, because I've got to an error message that I don't
understand and can't remove.

I have a class that works like a hash table, mapping from String to some
type.  I have two instances, one that is case insensitive for keys.  I
want to hide these instances from the rest of the code, which should only
use the class.  This class is called Dictionary.

In addition, for Dictionaries that map Strings to Strings, I have some
functions which do substitutions on Strings using their own contents. 
Possibly the first source of problems is that I can't find a way to
express these two classes together without multiple parameter type classes
(one parameter for the case/no case and one for the type returned):

class Dictionary d a where
  add'   :: d a -> (String, a) -> d a
  ...

instance Dictionary DictNoCase a where
  add' d (k, v) = ...

-- Dict is the underlying tree implementation and Maybe stores the
-- value for the null (empty string) key.
data DictNoCase a = DictNoCase (Dict a) (Maybe a)

class (Dictionary d String) => SubDictionary d where
  substitute :: d String -> String -> String
  ...

instance SubDictionary DictNoCase where
  substitute d s = ...

All the above compiles and seems correct (is it?).

I also provide an empty instance of the two instance types.  For
DictNoCase, this is
empty = DictCase Empty Nothing
where Empty is the empty type constructor for Dict

Now (almost there) elsewhere I want to define a data type that contains
two of these Dictionaries.  One stores String values.  The other stores
functions that take this same type and return a result and a copy of the
type:

data Context s f = (Dictionary s String, Dictionary f (CustomFn s f)) =>
Ctx {state :: s String,
 funcs :: f (CustomFn s f)}

type CustomFn s f = Context s f -> Arg -> IO (Context s f, Result s f)

data Result s f = Attr Name String
| Repeat (CustomFn s f)
...

newContext = Ctx empty emptyNC

(where empty is the case-sensitive empty dictionary)

Now THAT doesn't compile:

Template.lhs:60:
All of the type variables in the constraint `Dictionary s
String' are
already
in scope
(at least one must be universally quantified here)
When checking the existential context of constructor `Ctx'
In the data type declaration for `Context'

Template.lhs:60:
All of the type variables in the constraint `Dictionary f
(CustomFn s
f)' are
already in scope
(at least one must be universally quantified here)
When checking the existential context of constructor `Ctx'
In the data type declaration for `Context'

where line 60 is "data Context"

And I can't see what I've done wrong.  Any help gratefully received.

Cheers,
Andrew

-- 
personal web site: http://www.acooke.org/andrew
personal mail list: http://www.acooke.org/andrew/compute.html
___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell


Re: type classes, superclass of different kind

2003-12-11 Thread Brandon Michael Moore


On Thu, 11 Dec 2003, Robert Will wrote:

> Hello,
>
> As you will have noticed, I'm designing a little library of Abstract Data
> Structuresm here is a small excerpt to get an idea:
>
> class Collection coll a where
> ...
> (<+>) :: coll a -> coll a -> coll a
> reduce :: (a -> b) -> b
>   -> coll a -> b
> ...
>
> class Map map a b where
> ...
> (<+) :: map a b -> map a b -> map a b
> at :: map a b
>   -> a -> b
> ...
>
> Note that the classes don't only share similar types, they also have
> similar algebraic laws: both <+> and <+ are associative, and neither is
> commutative.
>
> Now I would like to have Collection to be a superclass of Map yielding the
> following typing
>
> reduce :: (Map map a b) =>
>   ((a, b) -> c) -> c
>   -> map a b -> c

Functional dependencies will do this.

class Collection coll a | coll -> a where
...
(<+>) :: coll -> coll -> coll
reduce :: (a -> b -> b) -> b -> coll -> b
...

class (Collection map (a,b)) => Map map a b | map -> a b where
...
(<+) :: map -> map -> map
at :: map -> a -> b

Now you make instances like

instance Collection [a] a where
   (<+>) = (++)
   reduce = foldr

instance (Eq a) => Map [(a,b)] a b where
   new <+ old = nubBy (\(x,_) (y,_) -> x == y) (new ++ old)
   at map x = fromJust (lookup x map)


> Note that in an OO programming language with generic classes (which is in
> general much less expressive than real polymorphism), I can write
>
> class MAP[A, B] inherit COLLECTION[TUPLE[A, B]]
>
> which has exactly the desired effect (and that's what I do in the
> imperative version of my little library).

This isn't exactly the same thing. In the OO code the interface
collections must provide consists of a set of methods. A particular
type, like COLLECTION[INTEGER] is the primitive unit that can implement
or fail to implement that interface.

In the Haskell code you require a collection to be a type constructor that
will give you a type with appropriate methods no matter what you apply
it to (ruling out special cases like extra compace sequences of booleans
and so on). A map is not something that takes a single argument and makes
a collection, so nothing can implement both of your map and collection
interfaces.

The solution is simple, drop the spurrious requirement that collections
be type constructors (or that all of our concrete collection types were
created by applying some type constructor to the element type). The
classes with functional dependencies say just that, our collection type
provides certain methods (involving the element types).

Collections were one of the examples in Mark Jones' paper on
functional dependencies ("Type Classes with Functional Dependencies",
linked from the GHC Extension:Functional Dependencies section of the
GHC user's guide).

> There seems to be no direct way to achieve the same thing with Haskell
> type classes (or any extension I'm aware of).  Here is a quesion for the
> most creative of thinkers: which is the design (in proper Haskell or a
> wide-spread extension) possibly include much intermediate type classes and
> other stuff, that comes nearest to my desire?
>
> I believe this question to be important and profound.  (We shouldn't
> make our functional designs more different from the OO ones, than they
> need to be.)  If I err, someone will tell me :->

What problems do objects solve? They let you give a common interface to
types with the same functionality, so you can make functions slightly
polymorphic in any argument type with the operations your code needs.
They organize your state. Then let you reuse code when you make a new
slightly different type. Am I missing anything here?

I think type classes are a much better solution than inheritance for
keeping track of which types have which functionality. (at least the way
interface by inheritance works in most typed and popular object oriented
languages.)

Inheritance only really works for notions that only involve the type doing
the inheriting, or are at least heavly centered around that type. I don't
think Functor can be represented as an interface, or at least not a very
natural one. Most langauges I know of (see Nice for an exception)  also
require you to declare the interface a class supports when you declare it,
which is really painful when you want your code to work with types that
were around before you were, like defining a class to represent
marshallable values for interface/serialization code.

Are there any advantages to inheritance for managing interfaces? Maybe
it takes a few minutes less to explain the first time around. 

Re: type classes, superclass of different kind

2003-12-11 Thread David Sankel
--- Robert Will <[EMAIL PROTECTED]> wrote:
-- > Here
-- > is a quesion for the
-- > most creative of thinkers: which is the design
(in
-- > proper Haskell or a
-- > wide-spread extension) possibly include much
-- > intermediate type classes and
-- > other stuff, that comes nearest to my desire?

Hello,

  I've often wondered the same thing.  I've found that
one can simulate several OO paradigms.  Note that
these aren't particularly elegant or simple.


Using Data Constructors:


> data Shape = Rectangle {topLeft :: (Int, Int),
bottomRight :: (Int,Int) } 
>| Circle {center :: (Int,Int), radius ::
Int } 

This allows you have a list of shapes 

> shapeList :: [Shape]
> shapeList = [ Rectangle (-3,3) (0,0), Circle (0,0) 3
]

When you want member functions, you need to specialize
the function for
all the constructors.

> height :: Shape -> Int
> height (Rectangle (a,b) (c,d)) = b - d
> height (Circle _ radius) = 2 * radius

Disadvantages:

1) When a new Shape is needed, one needs to edit the
original Shape source 
file.
2) If a member function is not implemented for a shape
subclass, it will lead
to a run-time error (instead of compile-time).

Advantages:

1) Simple Syntax
2) Allows lists of Shapes
3) Haskell98

Example: GHC's exception types
 
http://www.haskell.org/ghc/docs/latest/html/base/Control.Exception.html


Using Classes


Classes can be used to force a type have specific
functions to act upon it.
>From our previous example:

> class Shape a where
>   height :: a -> Int
>
> data Rectangle = Rectangle {topLeft :: (Int, Int),
bottomRight :: (Int,Int) }
> data Circle = Circle {center :: (Int,Int), radius ::
Int } 
> 
> instance Shape Circle where
>   height (Circle _ radius) = 2 * radius
>
> instance Shape Rectangle where
>   height (Rectangle (a,b) (c,d)) = b - d

In this case, something is a shape if it specifically
has the member 
functions associated with Shapes (height in this
case).

Advantages
1) Simple Syntax
2) Haskell98
3) Allows a user to easily add Shapes without
modifying the original source.
4) If a member function is not implemented for a shape
subclass, it will lead
to a compile-time error.

Disadvantages:
1) Lists of Shapes not allowed

Example: Haskell 98's Num class. 
http://www.haskell.org/ghc/


Classes with Instance holder.


There have been a few proposals of ways to get around
the List of Shapes 
problem with classes.  The Haskell98 ways looks like
this

> data ShapeInstance = ShapeInstance { ci_height ::
Int }

> toShapeInstance :: (Shape a) => a -> ShapeInstance
> toShapeInstance a = ShapeInstance { ci_height =
(height a) }

> instance Shape ShapeInstance where
>   height (ShapeInstance ci_height) = ci_height

So when we want a list of shapes, we can do

> shapeList = [ toShapeInstance (Circle (3,3) 3), 
>   toShapeInstance (Rectangle (-3,3)
(0,0) ) ]

Of course this also has it's disadvantages.  Everytime
a new memeber function is added, it must be noted in
the ShapeInstance declaration, the toShapeInstance
function, and the "instance Shape ShapeInstance"
declaration.

Using a haskell extention, we can get a little better.
 Existentially quantified data constructors gives us
this:

> data ShapeInstance = forall a. Shape a =>
ShapeInstance a
> 
> instance Shape ShapeInstance where
>   height (ShapeInstance a) = height a
>
> shapeList = [ ShapeInstance (Circle (3,3) 3), 
>   ShapeInstance (Rectangle (-3,3) (0,0)
) ]

The benefits of this method are shorter code, and no
need to update the ShapeInstance declaration every
time a new member function is added.


Records extention


A different kind of inheritance can be implemented
with enhanced haskell 
records.  See
http://research.microsoft.com/~simonpj/Haskell/records.html
and
http://citeseer.nj.nec.com/gaster96polymorphic.html
for in depth explinations.  I'm not sure if these have
been impemented or not, but it would work as follows.

The inheritance provided by the above extentions is
more of a data inheritance 
than a functional inheritance. Lets say all shapes
must have a color parameter:

> type Shape = {color :: (Int,Int,Int)}
> type Circle = Shape + { center :: (Int,Int), radius
:: (Int) }
> type Rectangle = Shape + { topLeft :: (Int,Int),
bottomRight :: (Int, Int) }

So now we can reference this color for any shape by
calling .color.

> getColor :: (a <: Shape ) -> a -> (Int,Int,Int)
> getColor a = a.color

I'm not sure how the records extention could be used
with Classes with instance 
holders to provide an even more plentiful OO
environment.

So I'll conclude this email with the observation that
Haskell supports some
OO constructs although not with the most elegance.

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell


RE: type classes, superclass of different kind

2003-12-11 Thread Niklas Broberg
Robert Will wrote:

Now I would like to have Collection to be a superclass of Map yielding the
following typing
reduce :: (Map map a b) =>
  ((a, b) -> c) -> c
  -> map a b -> c
Note that in an OO programming language with generic classes (which is in
general much less expressive than real polymorphism), I can write
class MAP[A, B] inherit COLLECTION[TUPLE[A, B]]

which has exactly the desired effect (and that's what I do in the
imperative version of my little library).
There seems to be no direct way to achieve the same thing with Haskell
type classes (or any extension I'm aware of).  Here is a quesion for the
most creative of thinkers: which is the design (in proper Haskell or a
wide-spread extension) possibly include much intermediate type classes and
other stuff, that comes nearest to my desire?
I don't know if I qualify as the most creative of thinkers, but I have a 
small library of ADSs that you may want to look at, it's at

http://www.dtek.chalmers.se/~d00nibro/algfk/

I recall having much the same problem as you did, my solution was to make 
maps (or Assoc as I call them) depend on tuple types, i.e. (somewhat 
simplified):

class (Collection c (k,v), Eq k) => Assoc c k v where
 lookup :: k -> c (k,v) -> v
 [...many more member functions here...]
This means that the type constructors for maps and collections have the same 
kind (* -> *), which makes it possible for me to say that an Assoc is 
actually also a Collection. A lot more info to be found off the link.

I believe this question to be important and profound.  (We shouldn't
make our functional designs more different from the OO ones, than they
need to be.)  If I err, someone will tell me :->
No need to recreate all the stupid things the OO world has come up with, 
better to do it correctly right away... ;)

/Niklas Broberg, d00nibro[at]dtek.chalmers.se

_
The new MSN 8: advanced junk mail protection and 2 months FREE* 
http://join.msn.com/?page=features/junkmail

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell


Re: type classes, superclass of different kind

2003-12-11 Thread Johannes Waldmann
Robert Will wrote:

Note that in an OO programming language with generic classes ...

(We shouldn't make our functional designs more different from the OO ones, 
> than they need to be.)

why should *we* care :-)

more often than not, OO design is resticted and misleading.

you see how most OO languages jump through funny hoops (in this case, 
generics) because they just lack proper higher-order types.

good luck with your library. but make sure you study existing (FP) 
designs, e. g. Chris Okasaki's Edison:
http://www.eecs.usma.edu/Personnel/okasaki/pubs.html#hw00
--
-- Johannes Waldmann,  Tel/Fax: (0341) 3076 6479 / 6480 --
-- http://www.imn.htwk-leipzig.de/~waldmann/ -

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell


type classes, superclass of different kind

2003-12-11 Thread Robert Will
Hello,

As you will have noticed, I'm designing a little library of Abstract Data
Structuresm here is a small excerpt to get an idea:

class Collection coll a where
...
(<+>) :: coll a -> coll a -> coll a
reduce :: (a -> b) -> b
  -> coll a -> b
...

class Map map a b where
...
(<+) :: map a b -> map a b -> map a b
at :: map a b
  -> a -> b
...

Note that the classes don't only share similar types, they also have
similar algebraic laws: both <+> and <+ are associative, and neither is
commutative.

Now I would like to have Collection to be a superclass of Map yielding the
following typing

reduce :: (Map map a b) =>
  ((a, b) -> c) -> c
  -> map a b -> c

Note that in an OO programming language with generic classes (which is in
general much less expressive than real polymorphism), I can write

class MAP[A, B] inherit COLLECTION[TUPLE[A, B]]

which has exactly the desired effect (and that's what I do in the
imperative version of my little library).

There seems to be no direct way to achieve the same thing with Haskell
type classes (or any extension I'm aware of).  Here is a quesion for the
most creative of thinkers: which is the design (in proper Haskell or a
wide-spread extension) possibly include much intermediate type classes and
other stuff, that comes nearest to my desire?

I believe this question to be important and profound.  (We shouldn't
make our functional designs more different from the OO ones, than they
need to be.)  If I err, someone will tell me :->


Robert
___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell


Re: Type classes and code generation

2003-06-17 Thread Keith Wansbrough
> Does this also mean that a dictionary class is created for every class, and
> a dictionary created for every instance?

Yes, exactly.  Every class is translated to a data type declaration, 
and every instance is translated to an element of that data type - a 
dictionary.  (Note that you can't actually write those declarations in 
Haskell 98 in general, because they can have polymorphic fields; but 
this is a simple extension to the language).

Take a look at one of the references Bernard put on the bottom of the
Wiki page I just created for further information.

http://www.haskell.org/hawiki/TypeClass

--KW 8-)

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell


Re: Type classes and code generation

2003-06-17 Thread Andreas Rossberg
Bayley, Alistair wrote:
When it's applied, the compiler will know the types of the arguments, won't
it?. Which means that you would generate a version of double for each
(applied) instance of Num. I don't doubt that there's a good reason this is
not done: code bloat? or are there simply some expressions that can't be
statically resolved?
I suppose I was thinking: is the language design sufficiently clever that
it's *always* possible for the compiler to infer the type instance in use,
or are there some situations where it's not possible to infer the instance,
so some kind of function dispatch mechanism is necessary?
This almost is an FAQ. Short answer: in general it is impossible to 
determine statically which instances/dictionaries are needed during 
evaluation. Their number may even be infinite. The main reason is that 
Haskell allows polymorphic recursion.

Consider the following (dumb) example:

f :: Eq a => [a] -> Bool
f [] = True
f (x:xs) = x == x && f (map (\x -> [x]) xs)
The number of instances used by f depends on the length of the argument 
list! Determining that statically is of course undecidable. If the list 
is infinite, f will use infinitely many instances (potentially, 
depending on lazy evaluation).

Another (non-Haskell-98) feature that prevents static resolution of type 
class dispatch are existential types, which actually provide the 
equivalent to "real" OO-style dynamic dispatch.

Of course, for most practical programs, the optimization you have in 
mind would be possible. I doubt compilers generally do it globally, 
though, because it requires whole program analysis, i.e. does not 
interfer well with separate compilation (beside other reasons).

| Andreas

--
Andreas Rossberg, [EMAIL PROTECTED]
"Computer games don't affect kids; I mean if Pac Man affected us
 as kids, we would all be running around in darkened rooms, munching
 magic pills, and listening to repetitive electronic music."
 - Kristian Wilson, Nintendo Inc.
___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell


RE: Type classes and code generation

2003-06-17 Thread Bayley, Alistair
> > Is there
> > some way of preventing the type mechanism from generating 
> code for the
> > instance type, as opposed to the class? 
> 
> I don't understand this question - does the explanation above help?


I could have been clearer with my questions. What I was wondering was: is
there some situation where the compiler can't statically determine the type
to be used?


> The function "double" will work on any type in the class Num, so the 
> compiler can't know which "+" function to use.

When it's applied, the compiler will know the types of the arguments, won't
it?. Which means that you would generate a version of double for each
(applied) instance of Num. I don't doubt that there's a good reason this is
not done: code bloat? or are there simply some expressions that can't be
statically resolved?

I suppose I was thinking: is the language design sufficiently clever that
it's *always* possible for the compiler to infer the type instance in use,
or are there some situations where it's not possible to infer the instance,
so some kind of function dispatch mechanism is necessary?


> Yes, roughly.  In Haskell, the compiler always figures out 
> the types of 
> everything at compile time.  This means it can often figure out which 
> bit of code to use at compile time as well - but because of 
> polymorphism, not always.  Consider this bit of code:
> 
> double :: Num a => a -> a
> double x = x + x
> 
> The function "double" will work on any type in the class Num, so the 
> compiler can't know which "+" function to use.  But it *doesn't* solve 
> this by run-time dispatch, like in C++.  Instead, it compiles double 
> like this:
> 
> double' :: NumDict a -> a -> a
> double' d x = let f = plus d
>   in x `f` x
> 
> where NumDict is a record a bit like this:
> 
> data NumDict a = NumDict { plus :: a -> a -> a,
>minus :: a -> a -> a,
>  fromInteger :: Integer -> a
>  ...
>  }
> 
> NumDict is called a "dictionary", and any time double' is called, the 
> caller must supply the right dictionary.  If you write
> 
> double 2.0
> 
> then the compiler sees that you've written a Double, and so supplies 
> the NumDict Double dictionary:
> 
> double' doubleNum 2.0
> 
> where doubleNum :: NumDict Double contains the methods for adding 
> Doubles, subtracting them, and converting from Integers to them.


This looks like a dispatching mechanism to me. However, I think I see that
this can still be done at compile-time. When double is applied to 2.0, the
compiler generates the double' doubleNum 2.0 code, which is still statically
resolvable. The advantage seems to be that you don't generate a double
function for each Num instance.

Does this also mean that a dictionary class is created for every class, and
a dictionary created for every instance?




> Getting back to your original question, there's a little subtlety in 
> Haskell to do with literals.  Whenever you type an integer 
> literal like  "2", what the compiler actually sees is "fromInteger 2".
> Another little subtlety called  "defaulting" (see 
> the Haskell 98 Report, in section 4.3.4) arranges that in this 
 
I knew about the "fromInteger" and similar treatment of literals, but the
defaulting system is news to me. I've skimmed over the Haskell report, but
details like this never sink in until you encounter them in practice...

 
> Instance exporting is not easy to control in Haskell; if you export a 
> type, then all its instances are exported along with it automatically.

Thanks. I wasn't sure how the export mechanism worked with regard to classes
and instances; I just took a (wrong) guess that you could control export of
classes and types separately.


*
The information in this email and in any attachments is 
confidential and intended solely for the attention and use 
of the named addressee(s). This information may be 
subject to legal professional or other privilege or may 
otherwise be protected by work product immunity or other 
legal rules.  It must not be disclosed to any person without 
our authority.

If you are not the intended recipient, or a person 
responsible for delivering it to the intended recipient, you 
are not authorised to and must not disclose, copy, 
distribute, or retain this message or any part of it.
*

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell


Re: Type classes and code generation

2003-06-17 Thread Keith Wansbrough
Alistair Bayley writes:

> Warning: Defaulting the following constraint(s) to type `Integer'
>`Num a' arising from the literal `2' at Main.lhs:3
> 
> This implies to me that the compiler is generating the code for (+) for the
> particular instance, rather than using a run-time dispatch mechanism to
> select the correct (+) function. Is this correct, or am I way off?  Does the
> compiler *always* know what the actual instances being used are?

Yes, roughly.  In Haskell, the compiler always figures out the types of 
everything at compile time.  This means it can often figure out which 
bit of code to use at compile time as well - but because of 
polymorphism, not always.  Consider this bit of code:

double :: Num a => a -> a
double x = x + x

The function "double" will work on any type in the class Num, so the 
compiler can't know which "+" function to use.  But it *doesn't* solve 
this by run-time dispatch, like in C++.  Instead, it compiles double 
like this:

double' :: NumDict a -> a -> a
double' d x = let f = plus d
  in x `f` x

where NumDict is a record a bit like this:

data NumDict a = NumDict { plus :: a -> a -> a,
   minus :: a -> a -> a,
   fromInteger :: Integer -> a
   ...
 }

NumDict is called a "dictionary", and any time double' is called, the 
caller must supply the right dictionary.  If you write

double 2.0

then the compiler sees that you've written a Double, and so supplies 
the NumDict Double dictionary:

double' doubleNum 2.0

where doubleNum :: NumDict Double contains the methods for adding 
Doubles, subtracting them, and converting from Integers to them.

Whenever it can, a good optimising compiler (like GHC) will try to 
remove these extra "dictionary applications", and use the code for the 
right method directly.  This is called "specialisation".

Getting back to your original question, there's a little subtlety in 
Haskell to do with literals.  Whenever you type an integer literal like 
"2", what the compiler actually sees is "fromInteger 2".  fromInteger 
has type Num a => Integer -> a, so this means that when you type an 
integer literal it is automatically converted to whatever numeric type 
is appropriate for the context.  In the context you give, there's still 
not enough information - it could be Int, or Integer, or Double, or 
several other things.  Another little subtlety called "defaulting" (see 
the Haskell 98 Report, in section 4.3.4) arranges that in this 
situation, the compiler will assume you mean Integer if that works, and 
failing that, it will try Double before giving up.  That's what the 
warning message you give is telling you.

> Is there
> some way of preventing the type mechanism from generating code for the
> instance type, as opposed to the class? 

I don't understand this question - does the explanation above help?

> If I am correct, does it work the same way across module boundaries? (I
> would think so.)

Yes, it does work automatically across instance boundaries.

> If a module exports a class but no instances for that
> class, then a user of that class would have to install their own instances.

Instance exporting is not easy to control in Haskell; if you export a 
type, then all its instances are exported along with it automatically.

> OTOH, if the class plus one or more instances were exported, then a user
> could use the supplied instance types, and the compiler would still generate
> code to use the specific instances.

>From the explanation above, you should see that the compiler generates
polymorphic code for any function with a type class in its type (e.g.,
"Num a => ..."), and it's the *caller* that supplies the code for the
specific instances (the dictionary).  But if the type is known at
compile time, then the compiler will fill in the dictionary itself,
and may even specialise it away.

The intention is that there is only one, global "instance space" - you
can't tightly control the export or not of specific instances, they
are pretty much always exported and all visible.  This isn't quite
true in practice, but it's the idea.

Hope this helps.

If you don't mind, I'm going to put this conversation up on the Wiki,
at

http://www.haskell.org/hawiki/TypeClass

--KW 8-)

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell


Re: Type classes and code generation

2003-06-17 Thread Bernard James POPE
> I had a discussion with someone over the type class mechanism and would like
> to clarify something.
> 
> When I compile this trivial program:
> 
> > module Main where
> > main = putStrLn (show (1 + 2))
> 
> with ghc -Wall, the compiler says:
> 
> Main.lhs:3:
> Warning: Defaulting the following constraint(s) to type `Integer'
>`Num a' arising from the literal `2' at Main.lhs:3
> 
> This implies to me that the compiler is generating the code for (+) for the
> particular instance, rather than using a run-time dispatch mechanism to
> select the correct (+) function. Is this correct, or am I way off? 

Hi,

I hope I've understod your question.

What this message is telling you is that the compiler is applying Haskell 98's
"defaulting" mechanism.

The numeric literals 1 and 2 in the code are overloaded, that is
they have type: Num a => a

When the program is run the calls to '+' and 'show' must be resolved to
particular instances. However the overloading of their arguments prevents
that. The overloading is thus ambiguous.

Haskell 98 has a rule that (very roughly) says when overloading is ambiguous
and it involves standard numeric classes, apply some defaults to resolve the
ambiguity. In this case the default rule is to resolve the outstanding
constraint 'Num a' with Integer (making the type of 1 and 2 Integer).

After defaulting the instances of + and show can be resolved. 

You can change the behaviour of defaulting, and even turn it off, try:

   module Main where 
   default ()
   ...

Compiling again with -Wall gives:

Ambiguous type variable(s) `a' in the constraint `Num a'
arising from the literal `2' at Foo.hs:6
In the second argument of `(+)', namely `2'
In the first argument of `show', namely `(1 + 2)'

You can also get the same effect as defaulting by putting explicit type
annotations in your program:

main = putStrLn (show ((1 + 2) :: Integer)) 

The Haskell Report doesn't say a whole lot about _how_ to implement the
type class overloading, though from what I understand,
most implementations use a similar algorithm (dictionary passing).

You can read all about typical implementations in the literature.
Google for "Type Class", "Implementation", and maybe even "Haskell".

> Does the compiler *always* know what the actual instances being used are? 

A smart compiler can specialise the calls to overloaded functions in
circumstances when the type(s) of its arguments are also known. This is a
good thing because it tends to reduce the cost of overloading at runtime.

More aggresive forms of specialisation are also possible and discussed in
the literature.

I think if you look up the papers on implementing type classes your
questions should be answered. Mail me if you need some references.

Cheers,
Bernie.
___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell


Type classes and code generation

2003-06-17 Thread Bayley, Alistair
I had a discussion with someone over the type class mechanism and would like
to clarify something.

When I compile this trivial program:

> module Main where
> main = putStrLn (show (1 + 2))

with ghc -Wall, the compiler says:

Main.lhs:3:
Warning: Defaulting the following constraint(s) to type `Integer'
 `Num a' arising from the literal `2' at Main.lhs:3

This implies to me that the compiler is generating the code for (+) for the
particular instance, rather than using a run-time dispatch mechanism to
select the correct (+) function. Is this correct, or am I way off? Does the
compiler *always* know what the actual instances being used are? Is there
some way of preventing the type mechanism from generating code for the
instance type, as opposed to the class? 


If I am correct, does it work the same way across module boundaries? (I
would think so.) If a module exports a class but no instances for that
class, then a user of that class would have to install their own instances.
OTOH, if the class plus one or more instances were exported, then a user
could use the supplied instance types, and the compiler would still generate
code to use the specific instances.


*
The information in this email and in any attachments is 
confidential and intended solely for the attention and use 
of the named addressee(s). This information may be 
subject to legal professional or other privilege or may 
otherwise be protected by work product immunity or other 
legal rules.  It must not be disclosed to any person without 
our authority.

If you are not the intended recipient, or a person 
responsible for delivering it to the intended recipient, you 
are not authorised to and must not disclose, copy, 
distribute, or retain this message or any part of it.
*

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell


Re: type classes vs. multiple data constructors

2003-02-17 Thread Andrew J Bromage
G'day.

On Mon, Feb 17, 2003 at 01:44:07AM -0500, Mike T. Machenry wrote:

>  I was wondering if it's better to define them as type classes with the
> operations defined in the class. What do haskellian's do?

I can't speak for other Haskellians, but on the whole, it depends.

Here's the common situation: You have a family of N abstractions.  (In
your case, N=2.)  The abstractions are similar in some ways and
different in some ways.  The most appropriate design depends largely
on what those similarities and differences are.

>From your definitions, it seems clear that there is some common
structure.  That suggests that a vanilla type class solution may
not be appropriate, because type classes do not directly support
common structure, only related operations.

Your solution wasn't bad:

> data PlayerState =
>   FugitiveState {
> tickets :: Array Ticket Int,
> fHistory :: [Ticket] } |
>   DetectiveState {
> tickets :: Array Ticket Int,
> dHistory :: [Stop] }

If the operations on the "tickets" field are different, or the
algorithms which operate on PlayerState are different for the
FugitiveState case and the DetectiveState case, this may be a good
design, because by not sharing structure, you're explicitly denying
any similarity (i.e. just because look the similar, that doesn't mean
they are similar).

If they are similar, then this may not be an appropriate design.
Ideally, you want to use language features and/or idioms which expose
the similarities (where they exist) and the differences (where they
exist).

Here's one design where the structural similarity is explicit:

data PlayerState
  = PlayerState {
tickets :: Array Ticket Int,
role:: RoleSpecificState
}

data RoleSpecificState
  = FugitiveState  { fHistory :: [Ticket] }
  | DetectiveState { dHistory :: [Stop] }

Depending on how similar the operations on the RoleSpecificState are
(say, if they are related by a common type signature, but have little
code in common), or if you want a design which is extensible to other
kinds of player (possibly at dynamic-link time) you may prefer to use
type classes to implement the role-specific states instead:

-- Warning: untested code follows

class RoleSpecificState a where
{- ... -}

data FugitiveState = FugitiveState { fHistory :: [Ticket] }

instance RoleSpecificState FugitiveState where
{- ... -}

data DetectiveState = DetectiveState { fHistory :: [Ticket] }

instance RoleSpecificState DetectiveState where
{- ... -}

data PlayerState
  = forall role. (RoleSpecificState role) =>
PlayerState {
tickets :: Array Ticket Int,
role:: role
}

(If you know anything about design patterns, you may recognise this as
being similar to the "Strategy" pattern.  This is no accident.)

It's hard to say what is the most appropriate design without looking at
the algorithms and operations which act on the PlayerState type and
analysing their similarities and differences.

> Oh and if I say
> Instance Foo Baz where
>   ...
> 
> and only define a few of the operations in Foo... bdoes Baz take on some
> default methods?

If you've declared default methods, yes.

Cheers,
Andrew Bromage
___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



type classes vs. multiple data constructors

2003-02-16 Thread Mike T. Machenry
I have a type that is as follows:

data PlayerState =
  FugitiveState {
tickets :: Array Ticket Int,
fHistory :: [Ticket] } |
  DetectiveState {
tickets :: Array Ticket Int,
dHistory :: [Stop] }

I have a few functions that act on PlayerState.

move :: PlayerState -> PlayerState
move DetectiveState ... =
move FugitivieState ... =

 I was wondering if it's better to define them as type classes with the
operations defined in the class. What do haskellian's do? Oh and if I say
Instance Foo Baz where
  ...

and only define a few of the operations in Foo... bdoes Baz take on some
default methods?

- mike
___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: Dispatch on what? (Was: seeking ideas for short lecture on type classes)

2003-02-04 Thread John Hörnkvist

On Tuesday, February 4, 2003, at 03:46 PM, Jerzy Karczmarczuk wrote:


I would say that - unless I am dead wrong, the OO languages such as 
Smalltalk
do not dispatch on dynamic types of a value. The receiver is known, so 
its vir.
f. table (belonging to the receiver's class) is known as well, the 
dispatching
is based on the *message identifiers* independently of subsidiary 
arguments.

Yes, normally only the receiver and "message identifier" matters. In 
languages like Java, where the type of the other arguments is 
considered, this is handled statically.

For languages like Smalltalk, Objective-C, etc, all that you know at 
compile time is that the receiver is an object. You don't know what 
kind of object. Thus you cannot use a static dispatch style or vtables 
as you would in a language like C++. Even when the type is bounded, 
vtables are not enough because of "categories" and "method packages" 
that add methods to classes at run time.

Dispatch is done on the "target" (receiver) and "selector" (message 
identifier).

So if you consider an expression like:
	target_expr doSomething:arg_expr
then you should break that up into
	v = target_expr
	f = lookup_method(v, "doSomething:")
	f(v, "doSomething:", argexpr).

You dispatch on the dynamic type of the target (it's class) and on the 
dynamic state of its method tables. Note that you cannot assume that 
the receiver has a method that matches the selector!

Dynamic method lookup is a fairly complicated and expensive process, 
and it's a barrier to many optimizations. This can be mitigated by 
program analysis and specialization or similar techniques; dynamic 
dispatch and the surrounding problems are getting fairly well 
researched.

Languages with dynamic dispatch:
* Brad J Cox, Object oriented programming: an evolutionary approach, 
Addison-Wesley Longman Publishing Co., Inc., 1986
* Apple Computer, Inc., The Objective-C Programming Language, 2002.
  http://developer.apple.com/techpubs/macosx/Cocoa/ObjectiveC/index.html
* Pieter J. Schoenmaker, Supporting the Evolution of Software, Ph.D. 
thesis, Eindhoven University of Technology, July 1, 1999.

Some research:
* Zoran Budimlic, Ken Kennedy, and Jeff Piper, The cost of being 
object-oriented: A preliminary study, Scientific Computing 7(2), 1999
* David Detlefs and Ole Agesen, Inlining of Virtual Methods, Proc. of 
13th ECOOP
* A Diwan. Understanding and improving the performance of modern 
programming
languages. Ph.D. thesis, University of Massachusetts at Amherst. 
1997
* Peeter Laud, Analysis for Object Inlining in Java; 
http://citeseer.nj.nec.com/laud01analysis.html
* Ole Agesen and Jens Palsberg and Michael I. Schwartzbach, Type 
Inference of {SELF}: Analysis of Objects with Dynamic and Multiple 
Inheritance, Lecture Notes in Computer Science, 
http://citeseer.nj.nec.com/agesen93type.html

Only after that - perhaps - some "reversions", message propagation 
depending on
the arg(s) value(s), etc. may take place, but all this is irrelevant...

Well,  "self" and the "selector" is usually an argument to the method, 
but otherwise I agree.

Regards,
John Hornkvist

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell


Dispatch on what? (Was: seeking ideas for short lecture on type classes)

2003-02-04 Thread Jerzy Karczmarczuk
This is a somewhat older thread, but I ask you to enlighten me.

Norman Ramsey wrote:

A fact that I know but don't understand the implication of is that
Haskell dispatches on the static type of a value, whereas OO languages
dispatch on the dynamic type of a value.  But I suspect I'll leave
that out :-)



Dean Herington:

Perhaps I misunderstand, but I would suggest that "fact" is, if not 
incorrect, at least oversimplified.  I would say Haskell dispatches on the
dynamic type of a value, in the sense that a single polymorphic function
varies its behavior based on the specific type(s) of its argument(s).
What may distinguish Haskell from typical OO languages (I'm not an expert
on them) is that in Haskell such polymorphic functions could (always or at
least nearly so) be specialized statically for their uses at different types.


Fergus Henderson wrote:
> I agree.  The above characterization is highly misleading.  It would be
> more accurate and informative to say that both Haskell and OO languages
> dispatch on the dynamic type of a value.
>




Now my brain ceased to understand... Are you sure that OO dispatch schemas
are based on the *argument* type?

I would say that - unless I am dead wrong, the OO languages such as Smalltalk
do not dispatch on dynamic types of a value. The receiver is known, so its vir.
f. table (belonging to the receiver's class) is known as well, the dispatching
is based on the *message identifiers* independently of subsidiary arguments.
Only after that - perhaps - some "reversions", message propagation depending on
the arg(s) value(s), etc. may take place, but all this is irrelevant...
Forgive me if I write stupidities.


Jerzy Karczmarczuk




___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



RE: seeking ideas for short lecture on type classes

2003-01-27 Thread Mark P Jones
Hi Norman,

| [looking for papers about type classes ...]
|   * Of all the many articles on the topic, which few might you
| recommend for beginners?

I wonder if my notes on "Functional Programming with Overloading and
Higher-Order Polymorphism" will be useful?  You can find them at:

  http://www.cse.ogi.edu/~mpj/pubs/springschool.html

They don't cover implementation aspects, but if your audience is more
interested in language/use than compilation issues, then I think they
might provide you with some reasonable starting material.

Hope this helps!
Mark

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: seeking ideas for short lecture on type classes

2003-01-27 Thread Norman Ramsey
Now that I have made it abundantly clear that my understanding of type
classes is highly imperfect, perhaps I will repeat my plea:

  * Can you recommend any interesting, elementary examples?

  * Of all the many articles on the topic, which few might you
recommend for beginners?  Would Faxen's static semantics be a good
place to start?  Jones's `Typing Haskell in Haskell'?  One of Phil
Wadler's papers (which one)?

Thanks again for any help,


Norman
___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: seeking ideas for short lecture on type classes

2003-01-27 Thread Dylan Thurston
On Mon, Jan 27, 2003 at 12:25:52PM +0200, Lauri Alanko wrote:
> On Mon, Jan 27, 2003 at 08:37:06PM +1100, Fergus Henderson wrote:
> > I agree.  The above characterization is highly misleading.  It would be
> > more accurate and informative to say that both Haskell and OO languages
> > dispatch on the dynamic type of a value.
> 
> What is the "dynamic type of a value" in Haskell, apart from existentials
> and Dynamic? Ordinary type class dispatch is all done based on the types of
> variables, not their values. All the dispatching could even be done at
> compile time by specializing everything...

I don't think this is true, even without existential types.
Polymorphic recursion may involve building dictionaries at run time,
which certainly approaches dynamic dispatch.

(Polymorphic recursion is one of Chris Okasaki's favorite tricks.  It
involves definitions like

data Tree a = Leaf a | Node (Tree [a]) (Tree [a])

in which the variable 'a' is used recursively at a different type.)

Best,
Dylan Thurston



msg12142/pgp0.pgp
Description: PGP signature


Re: seeking ideas for short lecture on type classes

2003-01-27 Thread Lauri Alanko
On Mon, Jan 27, 2003 at 08:37:06PM +1100, Fergus Henderson wrote:
> I agree.  The above characterization is highly misleading.  It would be
> more accurate and informative to say that both Haskell and OO languages
> dispatch on the dynamic type of a value.

What is the "dynamic type of a value" in Haskell, apart from existentials
and Dynamic? Ordinary type class dispatch is all done based on the types of
variables, not their values. All the dispatching could even be done at
compile time by specializing everything...


Lauri Alanko
[EMAIL PROTECTED]
___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: seeking ideas for short lecture on type classes

2003-01-27 Thread Fergus Henderson
On 26-Jan-2003, Norman Ramsey <[EMAIL PROTECTED]> wrote:
>  > > In a fit of madness, I have agreed to deliver a 50-minute lecture
>  > > on type classes to an audience of undergraduate students.  These
>  > > students will have seen some simple typing rules for F2 and will
>  > > have some exposure to Hindley-Milner type inference in the context
>  > > of ML.
>  > 
>  > Will they have had exposure to more "traditional" OO programming?  If
>  > so, it might be useful to note the difference between Haskell type
>  > classes and C++/Java/whatever classes, namely that Haskell decouples
>  > types and the interfaces that they support.  The advantage is that you
>  > can extend a type with a new interface at any point, not just when you
>  > define the type.
> 
> Hmm --- you are talking about the `instance' declarations, right?

Yes -- the fact that Haskell has separate instance declarations,
as opposed to making this information part of the `data' declaration.
In most OO languages inheritence relations need to be specified in the
type definition.

-- 
Fergus Henderson <[EMAIL PROTECTED]>  |  "I have always known that the pursuit
The University of Melbourne |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  | -- the last words of T. S. Garp.
___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: seeking ideas for short lecture on type classes

2003-01-27 Thread Fergus Henderson
On 24-Jan-2003, Norman Ramsey <[EMAIL PROTECTED]> wrote:
> In a fit of madness, I have agreed to deliver a 50-minute lecture
> on type classes to an audience of undergraduate students.  These
> students will have seen some simple typing rules for F2 and will
> have some exposure to Hindley-Milner type inference in the context
> of ML.  I am soliciting advice about
>   * Cool examples of type classes
>   * Papers I could read to explain how to implement type classes,
> especially if I could show the `dictionary translation' which
> is then followed by ordinary Hindley-Milner type inference
>   * Any other material on which I might base such a lecture

I quite like the idea of treating of type checking/inference as constraint
solving: ordinary Hindley-Milner style type inference involves
solving type unification constraints, and with type classes
you just generalize this to first-order predicate calculus
(type classes are predicates on types, and instance declarations
are clauses).

@InProceedings{demoen_et_al,
author =   {B. Demoen and M. {Garc\'{\i}a de la Banda} and
P.J. Stuckey},
title ={Type Constraint Solving for
Parametric and Ad-Hoc Polymorphism},
booktitle ={Proceedings of the 22nd
Australian Computer Science Conference},
pages ={217--228},
month =jan,
year = {1999},
location = {Auckland},
publisher ={Springer-Verlag},
isbn = {981-4021-54-7},
editor =   {J. Edwards},
}   

-- 
Fergus Henderson <[EMAIL PROTECTED]>  |  "I have always known that the pursuit
The University of Melbourne |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  | -- the last words of T. S. Garp.
___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: seeking ideas for short lecture on type classes

2003-01-27 Thread Fergus Henderson
On 26-Jan-2003, Dean Herington <[EMAIL PROTECTED]> wrote:
> On Sun, 26 Jan 2003, Norman Ramsey wrote:
> 
> > A fact that I know but don't understand the implication of is that
> > Haskell dispatches on the static type of a value, whereas OO languages
> > dispatch on the dynamic type of a value.  But I suspect I'll leave
> > that out :-)
> 
> Perhaps I misunderstand, but I would suggest that "fact" is, if not 
> incorrect, at least oversimplified.

I agree.  The above characterization is highly misleading.  It would be
more accurate and informative to say that both Haskell and OO languages
dispatch on the dynamic type of a value.

-- 
Fergus Henderson <[EMAIL PROTECTED]>  |  "I have always known that the pursuit
The University of Melbourne |  of excellence is a lethal habit"
WWW:   | -- the last words of T. S. Garp.
___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: seeking ideas for short lecture on type classes

2003-01-27 Thread Fergus Henderson
On 26-Jan-2003, John H?rnkvist <[EMAIL PROTECTED]> wrote:
> 
> On Saturday, January 25, 2003, at 04:14 AM, Andrew J Bromage wrote:
> 
> >G'day all.
> >
> >On Fri, Jan 24, 2003 at 06:13:29PM -0500, Norman Ramsey wrote:
> >
> >>In a fit of madness, I have agreed to deliver a 50-minute lecture
> >>on type classes to an audience of undergraduate students.  These
> >>students will have seen some simple typing rules for F2 and will
> >>have some exposure to Hindley-Milner type inference in the context
> >>of ML.
> >
> >Will they have had exposure to more "traditional" OO programming?  If
> >so, it might be useful to note the difference between Haskell type
> >classes and C++/Java/whatever classes, namely that Haskell decouples
> >types and the interfaces that they support.  The advantage is that you
> >can extend a type with a new interface at any point, not just when you
> >define the type.
> 
> While Java and C++ don't support it other object oriented languages do.

Some others do, some others don't.  And in fact it seems that most
mainstream OOP languages don't.  For example C#, Eiffel and Ada-95 don't,
if I recall correctly.  Sather does support it, but Sather is hardly
mainstream (the language is just about dead these days). 
GNU C++ used to support it, with the "signature" extension,
but doesn't anymore (support for that extension was dropped).
Of the vaguely mainstream OOP languages, I think only the dynamically-typed
ones support it.

-- 
Fergus Henderson <[EMAIL PROTECTED]>  |  "I have always known that the pursuit
The University of Melbourne |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  | -- the last words of T. S. Garp.
___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: seeking ideas for short lecture on type classes

2003-01-26 Thread Nick Name
On Sun, 26 Jan 2003 19:07:01 -0500 (EST)
Dean Herington <[EMAIL PROTECTED]> wrote:

>  What may distinguish Haskell from typical OO languages (I'm not an
>  expert on them) is that in Haskell such polymorphic functions could
>  (always or at least nearly so) be specialized statically for their
>  uses at different types.

Without existential types, one big difference from an OO language and
haskell is that in haskell you can't have a datastructure such as a
list, made up of elements of a certain type class but of different
types, whereas in an OO language (say eiffel) you can have a List[A]
wich can contain any sublcass of A.

In general, even with existential types, haskell lacks a subtype
relation. I always wonder if there really is no need for subtypes (and
would appreciate any pointer to a discussion on the topic).

Vincenzo

-- 
Fedeli alla linea, anche quando non c'è Quando l'imperatore è
malato, quando muore,o è dubbioso, o è perplesso.  Fedeli alla linea
la linea non c'è.  [CCCP]

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: seeking ideas for short lecture on type classes

2003-01-26 Thread Dean Herington
On Sun, 26 Jan 2003, Norman Ramsey wrote:

>  > > In a fit of madness, I have agreed to deliver a 50-minute lecture
>  > > on type classes to an audience of undergraduate students.  These
>  > > students will have seen some simple typing rules for F2 and will
>  > > have some exposure to Hindley-Milner type inference in the context
>  > > of ML.
>  > 
>  > Will they have had exposure to more "traditional" OO programming?  If
>  > so, it might be useful to note the difference between Haskell type
>  > classes and C++/Java/whatever classes, namely that Haskell decouples
>  > types and the interfaces that they support.  The advantage is that you
>  > can extend a type with a new interface at any point, not just when you
>  > define the type.
> 
> Hmm --- you are talking about the `instance' declarations, right?
> 
> A fact that I know but don't understand the implication of is that
> Haskell dispatches on the static type of a value, whereas OO languages
> dispatch on the dynamic type of a value.  But I suspect I'll leave
> that out :-)

Perhaps I misunderstand, but I would suggest that "fact" is, if not 
incorrect, at least oversimplified.  I would say Haskell dispatches on the
dynamic type of a value, in the sense that a single polymorphic function
varies its behavior based on the specific type(s) of its argument(s).
What may distinguish Haskell from typical OO languages (I'm not an expert
on them) is that in Haskell such polymorphic functions could (always or at
least nearly so) be specialized statically for their uses at different types.

Dean

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: seeking ideas for short lecture on type classes

2003-01-26 Thread John Hörnkvist

On Saturday, January 25, 2003, at 04:14 AM, Andrew J Bromage wrote:


G'day all.

On Fri, Jan 24, 2003 at 06:13:29PM -0500, Norman Ramsey wrote:


In a fit of madness, I have agreed to deliver a 50-minute lecture
on type classes to an audience of undergraduate students.  These
students will have seen some simple typing rules for F2 and will
have some exposure to Hindley-Milner type inference in the context
of ML.


Will they have had exposure to more "traditional" OO programming?  If
so, it might be useful to note the difference between Haskell type
classes and C++/Java/whatever classes, namely that Haskell decouples
types and the interfaces that they support.  The advantage is that you
can extend a type with a new interface at any point, not just when you
define the type.


While Java and C++ don't support it other object oriented languages do.

Extending and amending the capabilities of existing classes is 
important in Objective-C (through categories and posing) and TOM.

Smalltalk also supports it.

Regards,
John Hornkvist

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell


Re: seeking ideas for short lecture on type classes

2003-01-26 Thread Norman Ramsey
 > > In a fit of madness, I have agreed to deliver a 50-minute lecture
 > > on type classes to an audience of undergraduate students.  These
 > > students will have seen some simple typing rules for F2 and will
 > > have some exposure to Hindley-Milner type inference in the context
 > > of ML.
 > 
 > Will they have had exposure to more "traditional" OO programming?  If
 > so, it might be useful to note the difference between Haskell type
 > classes and C++/Java/whatever classes, namely that Haskell decouples
 > types and the interfaces that they support.  The advantage is that you
 > can extend a type with a new interface at any point, not just when you
 > define the type.

Hmm --- you are talking about the `instance' declarations, right?

A fact that I know but don't understand the implication of is that
Haskell dispatches on the static type of a value, whereas OO languages
dispatch on the dynamic type of a value.  But I suspect I'll leave
that out :-)


N
___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: seeking ideas for short lecture on type classes

2003-01-24 Thread Andrew J Bromage
G'day all.

On Fri, Jan 24, 2003 at 06:13:29PM -0500, Norman Ramsey wrote:

> In a fit of madness, I have agreed to deliver a 50-minute lecture
> on type classes to an audience of undergraduate students.  These
> students will have seen some simple typing rules for F2 and will
> have some exposure to Hindley-Milner type inference in the context
> of ML.

Will they have had exposure to more "traditional" OO programming?  If
so, it might be useful to note the difference between Haskell type
classes and C++/Java/whatever classes, namely that Haskell decouples
types and the interfaces that they support.  The advantage is that you
can extend a type with a new interface at any point, not just when you
define the type.

Cheers,
Andrew Bromage
___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: seeking ideas for short lecture on type classes

2003-01-24 Thread Christopher Milton
--- Norman Ramsey <[EMAIL PROTECTED]> wrote:
> In a fit of madness, I have agreed to deliver a 50-minute lecture
> on type classes to an audience of undergraduate students.  These
> students will have seen some simple typing rules for F2 and will
> have some exposure to Hindley-Milner type inference in the context
> of ML.  I am soliciting advice about
>   * Cool examples of type classes
>   * Papers I could read to explain how to implement type classes,
> especially if I could show the `dictionary translation' which
> is then followed by ordinary Hindley-Milner type inference
>   * Any other material on which I might base such a lecture
> I'm especially in need of a guide to the literature, as
> the `Haskell bookshelf' at haskell.org is silent on the topic
> of type classes.

http://www.research.avayalabs.com/user/wadler/topics/type-classes.html

http://www.dcs.qmul.ac.uk/SEL-HPC/Articles/GeneratedHtml/functional.imptype.html

http://haskell.readscheme.org/lang_sem.html

=
Christopher Milton
[EMAIL PROTECTED]

__
Do you Yahoo!?
Yahoo! Mail Plus - Powerful. Affordable. Sign up now.
http://mailplus.yahoo.com
___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



seeking ideas for short lecture on type classes

2003-01-24 Thread Norman Ramsey
In a fit of madness, I have agreed to deliver a 50-minute lecture
on type classes to an audience of undergraduate students.  These
students will have seen some simple typing rules for F2 and will
have some exposure to Hindley-Milner type inference in the context
of ML.  I am soliciting advice about
  * Cool examples of type classes
  * Papers I could read to explain how to implement type classes,
especially if I could show the `dictionary translation' which
is then followed by ordinary Hindley-Milner type inference
  * Any other material on which I might base such a lecture
I'm especially in need of a guide to the literature, as
the `Haskell bookshelf' at haskell.org is silent on the topic
of type classes.

Please send me your recommendations.


Norman Ramsey
___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: type classes and generality

2001-07-09 Thread Lennart Augustsson

"Alexander V. Voinov" wrote:

> Hi All,
>
> Lennart Augustsson wrote:
> > > Each pseudorandom generator generates a countable sequence of values,
> > > which is isomorphic to a sequence of integers. In good old (Turbo)C we
> > > got something between 0 and MAXINT and then divided by (double)MAXINT.
> > > Can't _this_ be done in Haskell?
> >
> > Of course it can be done, but not in class Real, you have to be in Fractional.
> > I'm not sure why Real would be the class of choice for this problem anyway.
> > I'd think that Fractional or RealFrac would be more appropriate.
>
> I apologize for ignorance, I probably did not read this part of the doc
> attentively. But informally, the word 'Real' is widely used to denote a
> completely ordered field, and there is a theorem to change 'a' to 'the'.
> It's counterintuitive to use Real in any other meaning, I think.

I agree.

-- Lennart



___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: type classes and generality

2001-07-09 Thread Alexander V. Voinov

Hi All,

Lennart Augustsson wrote:
> > Each pseudorandom generator generates a countable sequence of values,
> > which is isomorphic to a sequence of integers. In good old (Turbo)C we
> > got something between 0 and MAXINT and then divided by (double)MAXINT.
> > Can't _this_ be done in Haskell?
> 
> Of course it can be done, but not in class Real, you have to be in Fractional.
> I'm not sure why Real would be the class of choice for this problem anyway.
> I'd think that Fractional or RealFrac would be more appropriate.

I apologize for ignorance, I probably did not read this part of the doc
attentively. But informally, the word 'Real' is widely used to denote a
completely ordered field, and there is a theorem to change 'a' to 'the'. 
It's counterintuitive to use Real in any other meaning, I think.

Alexander

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: type classes and generality

2001-07-09 Thread Lennart Augustsson

"Alexander V. Voinov" wrote:

> Hi All,
>
> Fergus Henderson wrote:
> > Ah, now I think I understand your problem.  You want to `random' to
> > generate random numbers that span all the possible values of the type
> > within the range [0, 1], or at least a substantial subset, but the "Real"
> > class doesn't let you generate any numbers other than integers.
> > The above approach will give you random numbers from `random', but they
> > will only ever be 0 or 1, so maybe they are not as random as you needed! ;-)
>
> Each pseudorandom generator generates a countable sequence of values,
> which is isomorphic to a sequence of integers. In good old (Turbo)C we
> got something between 0 and MAXINT and then divided by (double)MAXINT.
> Can't _this_ be done in Haskell?

Of course it can be done, but not in class Real, you have to be in Fractional.
I'm not sure why Real would be the class of choice for this problem anyway.
I'd think that Fractional or RealFrac would be more appropriate.

-- Lennart



___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: type classes and generality

2001-07-09 Thread Fergus Henderson

On 09-Jul-2001, Alexander V. Voinov <[EMAIL PROTECTED]> wrote:
> Hi All,
> 
> Fergus Henderson wrote:
> > Ah, now I think I understand your problem.  You want to `random' to
> > generate random numbers that span all the possible values of the type
> > within the range [0, 1], or at least a substantial subset, but the "Real"
> > class doesn't let you generate any numbers other than integers.
> > The above approach will give you random numbers from `random', but they
> > will only ever be 0 or 1, so maybe they are not as random as you needed! ;-)
> 
> Each pseudorandom generator generates a countable sequence of values,
> which is isomorphic to a sequence of integers. In good old (Turbo)C we
> got something between 0 and MAXINT and then divided by (double)MAXINT.
> Can't _this_ be done in Haskell?

Sure, it can be done, but not on a value whose type is constrained only by
the "Real" class, because the "Real" class doesn't have any division operator!

Haskell's "/" operator is a member of the "Floating" class, and "Floating"
is not a base class of "Real".  It is a base class of the "RealFrac"
class, so you could use that approach for "RealFrac"... but the original
poster was asking for the solution to a more difficult problem.

-- 
Fergus Henderson <[EMAIL PROTECTED]>  |  "I have always known that the pursuit
The University of Melbourne |  of excellence is a lethal habit"
WWW:   | -- the last words of T. S. Garp.

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: type classes and generality

2001-07-09 Thread Alexander V. Voinov

Hi All,

Fergus Henderson wrote:
> Ah, now I think I understand your problem.  You want to `random' to
> generate random numbers that span all the possible values of the type
> within the range [0, 1], or at least a substantial subset, but the "Real"
> class doesn't let you generate any numbers other than integers.
> The above approach will give you random numbers from `random', but they
> will only ever be 0 or 1, so maybe they are not as random as you needed! ;-)

Each pseudorandom generator generates a countable sequence of values,
which is isomorphic to a sequence of integers. In good old (Turbo)C we
got something between 0 and MAXINT and then divided by (double)MAXINT.
Can't _this_ be done in Haskell?

Alexander

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: type classes and generality

2001-07-09 Thread Fergus Henderson

On 09-Jul-2001, Norman Ramsey <[EMAIL PROTECTED]> wrote:
>  > On 09-Jul-2001, Norman Ramsey <[EMAIL PROTECTED]> wrote:
>  > > I'm trying to model probability and leave the
>  > > representation of probability unspecified other than
>  > > it must be class Real.  But I'm having trouble with
>  > > random numbers; how can I show that if a type has class Real,
>  > > it also has class Random.Random?  Is there a way to accomplish
>  > > this goal other than by changing the library?
>  > 
>  > I'm not sure if I fully understand your goal.
>  > But one thing you can do is to define a wrapper type
>  > 
>  >newtype WrapReal r = WrapReal r
>  > 
>  > and make the wrapper an instance of Random.Random
>  > if the underlying type is an instance of Real
>  > 
>  >instance Real r => Random.Random (WrapReal r) where
>  >...
>  > 
>  > Then you can use the wrapper type whenever you want to get a random number.
> 
> The problem is that without intensional type analysis, I wouldn't know
> how to fill in the instance methods in the `...'

How about like so?

import Random

newtype WrapReal r = WrapReal r
wrap r = WrapReal r
unwrap (WrapReal r) = r

instance Real r => Random (WrapReal r) where
random = randomR (wrap 0, wrap 1)
randomR (min, max) gen0 = (wrap (fromInteger r), gen) where
(r, gen) = randomR (imin, imax) gen0
imin = ceiling (toRational (unwrap min))
imax = floor (toRational (unwrap max))

Ah, now I think I understand your problem.  You want to `random' to
generate random numbers that span all the possible values of the type
within the range [0, 1], or at least a substantial subset, but the "Real"
class doesn't let you generate any numbers other than integers.
The above approach will give you random numbers from `random', but they
will only ever be 0 or 1, so maybe they are not as random as you needed! ;-)

The proof that you can only generate integers values of the real type
(by which I mean values of the real type for which toRational returns
an integer) is that the only methods of class Real which return values
of the type are "fromInteger", and the operators ("+", "*", "-",
"negate", "abs", and "signum"), which are all integer-preserving --
when given integers they will always return other integers.
So by induction you can't generate any non-integers.

I'd advise you to  add an extra "Random t" class constraint to those
parts of your application that rely on generating random numbers.
If you find yourself using `Real t, Random t' frequently, you can
use a derived class for that:

class (Random t, Real t) => RandomReal a where
-- no methods

-- 
Fergus Henderson <[EMAIL PROTECTED]>  |  "I have always known that the pursuit
The University of Melbourne |  of excellence is a lethal habit"
WWW:   | -- the last words of T. S. Garp.

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



type classes and generality

2001-07-09 Thread Tom Pledger

Norman Ramsey writes:
 :
 | how can I show that if a type has class Real, it also has class
 | Random.Random?  Is there a way to accomplish this goal other than
 | by changing the library?

How about the default-implementations-as-external-functions approach
Marcin suggested, adapted for Real instead of Bounded and Enum?

http://www.mail-archive.com/haskell@haskell.org/msg05658.html

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: type classes and generality

2001-07-09 Thread Norman Ramsey

 > On 09-Jul-2001, Norman Ramsey <[EMAIL PROTECTED]> wrote:
 > > I'm trying to model probability and leave the
 > > representation of probability unspecified other than
 > > it must be class Real.  But I'm having trouble with
 > > random numbers; how can I show that if a type has class Real,
 > > it also has class Random.Random?  Is there a way to accomplish
 > > this goal other than by changing the library?
 > 
 > I'm not sure if I fully understand your goal.
 > But one thing you can do is to define a wrapper type
 > 
 >  newtype WrapReal r = WrapReal r
 > 
 > and make the wrapper an instance of Random.Random
 > if the underlying type is an instance of Real
 > 
 >  instance Real r => Random.Random (WrapReal r) where
 >  ...
 > 
 > Then you can use the wrapper type whenever you want to get a random number.

The problem is that without intensional type analysis, I wouldn't know
how to fill in the instance methods in the `...'

N

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: type classes and generality

2001-07-09 Thread Fergus Henderson

On 09-Jul-2001, Norman Ramsey <[EMAIL PROTECTED]> wrote:
> I'm trying to model probability and leave the
> representation of probability unspecified other than
> it must be class Real.  But I'm having trouble with
> random numbers; how can I show that if a type has class Real,
> it also has class Random.Random?  Is there a way to accomplish
> this goal other than by changing the library?

I'm not sure if I fully understand your goal.
But one thing you can do is to define a wrapper type

newtype WrapReal r = WrapReal r

and make the wrapper an instance of Random.Random
if the underlying type is an instance of Real

instance Real r => Random.Random (WrapReal r) where
...

Then you can use the wrapper type whenever you want to get a random number.

-- 
Fergus Henderson <[EMAIL PROTECTED]>  |  "I have always known that the pursuit
The University of Melbourne |  of excellence is a lethal habit"
WWW:   | -- the last words of T. S. Garp.

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



type classes and generality

2001-07-09 Thread Norman Ramsey

I'm trying to model probability and leave the
representation of probability unspecified other than
it must be class Real.  But I'm having trouble with
random numbers; how can I show that if a type has class Real,
it also has class Random.Random?  Is there a way to accomplish
this goal other than by changing the library?


Norman

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: question on type classes

2001-05-08 Thread Ashley Yakeley

At 2001-05-08 03:07, Markus Lauer wrote:

>Hugs sais ERROR Test.hs:20 - syntax error in instance head (constructor 
>   expected)

Invoke as 'hugs -98' to switch on extensions. Hugs will then complain of 
overlapping instances:

instance FooList Char
instance Foo a => FooList a

Yes, I know Char is not an instance of Foo. See the "Anomalous Class 
Fundep Inference" thread.

-- 
Ashley Yakeley, Seattle WA


___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



question on type classes

2001-05-08 Thread Markus Lauer


Is it possible in Haskell to define a type class like Show, which
has a generic implementation for Lists and a special one for
[Char], but (in contrast to Show) where Char is not in this Class

I'd like to have something like the following, but this example
doesn't work:

---
module Test where

class Foo a where
foo :: a -> a

 

instance FooList a => Foo [a] where
foo lst = fooList lst



class FooList a where
fooList :: [a] -> [a]
 


genericImpl :: Foo a => [a] -> [a]
genericImpl = ...

specialImpl :: String -> String
specialImpl = 

instance FooList Char where
fooList s = specialImpl s
.

instance Foo a => FooList a where
fooList lst = genericImpl lst
.

-

Hugs sais ERROR Test.hs:20 - syntax error in instance head (constructor 
   expected)

ghc (5.00) sais Test.hs:20:
Illegal instance declaration for `FooList a'
(the instance type must be of form (T a b c)
 where T is not a synonym, and a,b,c are distinct type variables)

is there a better way, than to copy the instance declaration of
FooList for every a in that is in class Foo?

Thanks for any hint,

Markus

-- 
Markus Lauer <[EMAIL PROTECTED]>



___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: Disjoint type classes

2001-03-05 Thread Marcin 'Qrczak' Kowalczyk

Thu, 18 Feb 1988 08:17:58 +0100, Jose Emilio Labra Gayo <[EMAIL PROTECTED]> pisze:

> Which doesn't work because Haskell doesn't detect that
> "Integral" and "Fractional" are disjoint.

And indeed there is no disjointness concept in the language.
Nothing prevents from making a type an instance of both.

> Is there a way to implement these type classes with current Haskell
> implementations?

I'm afraid not. In the standard way you must decide for each type
separately. At most you could use ghc with -fallow-overlapping-instances
-fallow-undecidable-instances, which would allow to define one of your
instances - the other would have to be defined for each type separately;
but these options are not nice.

-- 
 __("<  Marcin Kowalczyk * [EMAIL PROTECTED] http://qrczak.ids.net.pl/
 \__/
  ^^  SYGNATURA ZASTÊPCZA
QRCZAK


___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Disjoint type classes

2001-03-05 Thread Jose Emilio Labra Gayo

I have a large program where I would like to include disjoint type classes
into a new type class.

My problem can be reduced to the following example (taken from [1]):

> class Num a => Dividable a
>   where dividedBy :: a -> a -> a

> instance Fractional a => Dividable a where
> dividedBy = (/)

> instance Integral a => Dividable a where
>   dividedBy = div

Which doesn't work because Haskell doesn't detect that
"Integral" and "Fractional" are disjoint.

Is there a way to implement these type classes with current Haskell
implementations?

[1] K. Glynn, M. Sulzmann,  P.J. Stuckey
Type Classes and Constraint Handling Rules
http://www.cs.mu.oz.au/tr_submit/test/cover_db/mu_TR_2000_7.html

Best regards, Jose Labra




___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: Are anonymous type classes the right model at all? (replying to Re: Are fundeps the right model at all?)

2001-01-08 Thread Tom Pledger

Marcin 'Qrczak' Kowalczyk writes:
 [...]
 > My new record scheme proposal does not provide such lightweight
 > extensibility, but fields can be added and deleted in a controlled
 > way if the right types and instances are made.

Johan Nordlander must be on holiday or something, so I'll deputise for
him.   :-)

O'Haskell also has add-a-field subtyping.  Here's the coloured point
example (from http://www.cs.chalmers.se/~nordland/ohaskell/survey.html):

   struct Point =
  x,y :: Float

   struct CPoint < Point =
  color :: Color

Regards,
Tom

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



First Class Modules? was Re: Are anonymous type classes the right model at all?

2001-01-07 Thread Adrian Hey

Hello,

All this talk about Haskell classes, ML modules and improved record types
reminds me of the rumours of a "First Class Modules" system for Haskell,
but the only documentation I found was a fairly brief document that looked
like an application for a research grant. So...

Could somebody explain what a first class module is?
How does it differ from a record?
What could I do with a first class module (if Haskell provided them)?

Thanks
-- 
Adrian Hey


___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: Are anonymous type classes the right model at all? (replying to Re: Are fundeps the right model at all?)

2001-01-05 Thread Julian Assange

Peter Douglass <[EMAIL PROTECTED]> writes:

> Julian Assange wrote (Dec 28, 2000):
> 
> > This is why all non S-exp like lanaguage are doomed to progressive
> > syntactic cancer as the useful parts of operator name space and syntax
> > space become progressively polluted and mutated by one fad after
> > another.
> 
> Could you expand on this? I would think that all languages have identifies
> that, through common usage become standardized, and that this meaning
> becomes a de-facto part of the language.  Do you feel that this has not
> happened in Lisp/Scheme?

The identifier space in lisp/scheme has wide tree depth and is
(essentially) lexically scoped. Infix operator identifiers in other
languages are the antithesis of this. It could be argued, both fairly
and unfairly, that the verbosity of S-exp bracketing leaves short
identifiers less desirable than they otherwise would be, however
tree-width arguments remain.

Polution of syntax space is a more difficult problem. As new syntactic
axioms are intruded, they should remain consistant with the existing
syntax elements. This poses ever increasing restraint on the evolution
of the language. New syntax elements appear less intuitive and more
arbitary in an attempt to fit in with the morass of ever increasing
restraints. If these restraints are not honnored, the language becomes
inconsistant. Eventually the language is guarenteed to become either
inconsistant or moribund as the number of interactions between
language elements overwhelms a language designers attempts understand
them.

The same is even more true of language semantics. The trouble lays in
finding initial axioms which can cleave large sections of future
concept space between them.

--
 Julian Assange|If you want to build a ship, don't drum up people
   |together to collect wood or assign them tasks and
 [EMAIL PROTECTED]  |work, but rather teach them to long for the endless
 [EMAIL PROTECTED]  |immensity of the sea. -- Antoine de Saint Exupery

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



RE: Are anonymous type classes the right model at all? (replying to Re: Are fundeps the right model at all?)

2001-01-05 Thread Peter Douglass

Julian Assange wrote (Dec 28, 2000):

> This is why all non S-exp like lanaguage are doomed to progressive
> syntactic cancer as the useful parts of operator name space and syntax
> space become progressively polluted and mutated by one fad after
> another.

Could you expand on this? I would think that all languages have identifies
that, through common usage become standardized, and that this meaning
becomes a de-facto part of the language.  Do you feel that this has not
happened in Lisp/Scheme?

--PeterD

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: Are anonymous type classes the right model at all? (replying to Re: Are fundeps the right model at all?)

2001-01-03 Thread Stefan Karrmann

A syntax to choose the active instances may be useful, too.

E.g.:

use EccenticOrd, SetCollection in exp

then in exp the instances  EccenticOrd, SetCollection are known (or preferred).
This is similiar to the open syntax in Cayenne.

-- 
Stefan Karrmann

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: Are anonymous type classes the right model at all? (replying to Re: Are fundeps the right model at all?)

2000-12-30 Thread Marcin 'Qrczak' Kowalczyk

Fri, 29 Dec 2000 00:37:45 -0800, John Meacham <[EMAIL PROTECTED]> pisze:

> http://www.cse.ogi.edu/~mpj/pubs/lightrec.html

I've read it and posted some comments in February 2000. There was no
answer AFAIR. Here are they again, slightly edited and extended:

I don't understand why to separate kinds of rows and record types,
instead of having "a type which is known to be a record type", at
least on the level visible for the programmer. So instead of
type Pointr = (r | x::Int, y::Int)
type Colored  r = (r | c::Color)
type ColoredPoint r = Point (Colored r)
p :: {ColoredPoint()}
-- Point, Colored, ColoredPoint :: row -> row
it would be
type Pointr = {r | x::Int, y::Int}
type Colored  r = {r | c::Color}
type ColoredPoint r = Point (Colored r)
p :: ColoredPoint()
-- Point, Colored, ColoredPoint :: recordType -> recordType
-- where recordType is something like a subkind of *.



It is bad to require the programmers to think in advance that a type
is going to be subtyped, and write elaborated
type Point r = (r | x::Int, y::Int)
... {Point()} ...
instead of simpler
type Point = {x::Int, y::Int}
... Point ...
which is not extensible.



I got used to () as a unit type. It would be a pity to lose it.



A minor problem. If tuples are records, field names should be such
that alphabetic order gives the sequential order of fields, or have
a special rule of field ordering for names of tuple fields...



In general I don't quite like the fact that records are getting more
anonymous. Magical instances of basic classes? How inelegant.

If I want the record type to have an identity, it will have to be
wrapped in a newtype, so I must think at the beginning if I will ever
want to write specialized insances for it and then all the code will
depend on the decision. Currently a datatype with named fields has
both an identity and convenient syntax of field access. (And why
newtype is not mentioned in section 5.1?)

I like name equivalence where it increases type safety. Extensible
records promote structural equivalence.

Unfortunately the proposal seems to increase the number of
irregularities and inelegant rules...

If expr.Constructor for a multiparameter constructor yields a tuple,
then for an unary constructor it should give a 1-tuple, no? I know
it would be extremely inconvenient, especially as newtypes are more
used, so I don't propose it, but it is getting less regular. What
about nullary constructors - empty tuple? :-)

I don't say that I don't like the proposal at all, or that I never
wanted to have several types with the same field names. But it is
not clean for me, it's a compromise between usability and elegance,
and from the elegance point of view I like current records more.

Maybe it would be helpful to show how to translate a program with
extensible records to a program without them (I guess it's possible
in a quite natural way, but requires global transformation of the
whole program).



Extensible records makes a syntactic difference between field access
and function call. So if one wants to export a type abstractly or
simply to provide functions operating on it without fixing the fact
that they are physically fields, he ends in writing functions like

size:: MyRecord -> Int
size x = x.MyRecord.size

which are unnecessary now, even if size is simply a field.

It reminds me of C++ which wants us to provide methods for accessing
data fields (for allowing them to be later redefined as methods,
and for allowing everything to be uniformly used with "()" after the
feature name). Ugh.



My new record scheme proposal does not provide such lightweight
extensibility, but fields can be added and deleted in a controlled
way if the right types and instances are made.

The distinction between having a field and having a supertype is
blurred. Similarly between having itself a field called foo and having
a supertype which has a field called foo. Similarly between creating
a record by adding fields to another record and creating a record by
putting another record as one of fields. Similarly between casting
to a supertype by removing some fields and extracting the supertype
represented by a field.

An advantage is that the interface of records does not constrain the
representation in any way. It's up to how instances are defined,
with the provision of natural definitions for records implemented
physically as product types.

For example supplying a color for a colorless point and the reverse
operation can be written thus:
addColor :: (Record cp, cp.point :: p, cp.color :: Color)
 => p -> Color -> cp
addColor p c = record point = p; color = c

removeColor :: (cp.point :: p) => cp -> p
   

Re: Are anonymous type classes the right model at all? (replying to Re: Are fundeps the right model at all?)

2000-12-29 Thread John Meacham

I also like the approach of generalizing the record system, although I
have not evaluated your particular proposal. Speaking of record
improvements why is 
http://www.cse.ogi.edu/~mpj/pubs/lightrec.html
not listed on the future of haskell page? has it already been determined
to not be in the future of haskell or has no one gotten around to it?
Does anyone else read this proposal and drool? 

Speaking of this proposal does anyone else see parallels between the
lightweight modules proposal and the implicit parameters proposal
http://www.cse.ogi.edu/~jlewis/implicit.ps.gz as implemented in ghc.

in particular implicit parameters seem like they would be able to be
implemented as syntatic sugar on the lightweight module system,

one could rewrite implicit parameters as every function taking a record
which we can call 'imp' now '?foo' can be rewritten as 'imp.foo' and the
'with ?foo = 1' construct can be rewritten as nimp = {imp | foo := 1}
and then passing nimp to all called functions. I have not thought this
too far thorough so I could be missing something obvious but I think it
shows potential at least for the unification of two popular extensions. 

and I am pretty sure this was too obvious to mention in the lightweight
records paper but the section of (.foo) being equivalent to 
(\{_|foo=v} -> v) seems appropriate.

John

-- 
--
John Meacham   http://www.ugcs.caltech.edu/~john/
California Institute of Technology, Alum.  [EMAIL PROTECTED]
--

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: Are anonymous type classes the right model at all? (replying to Re: Are fundeps the right model at all?)

2000-12-28 Thread Julian Assange

George Russell <[EMAIL PROTECTED]> writes:

> I'm writing, but that shouldn't be too hard to tweak.  In particular I have
> followed SML in using "." to express qualification by something, even though
> Haskell already used "." for something else, because I can't be bothered right
> now to dig up a better symbol.

This is why all non S-exp like lanaguage are doomed to progressive
syntactic cancer as the useful parts of operator name space and syntax
space become progressively polluted and mutated by one fad after
another.

--
 Julian Assange|If you want to build a ship, don't drum up people
   |together to collect wood or assign them tasks
 [EMAIL PROTECTED]  |and work, but rather teach them to long for the endless
 [EMAIL PROTECTED]  |immensity of the sea. -- Antoine de Saint Exupery

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: Are anonymous type classes the right model at all? (replying to Re: Are fundeps the right model at all?)

2000-12-26 Thread Marcin 'Qrczak' Kowalczyk

Tue, 26 Dec 2000 12:10:55 +1100, Fergus Henderson <[EMAIL PROTECTED]> pisze:

> Mercury's module system allows instance declarations (which, as in
> Haskell 98, are unnamed) to be selectively exported.

If they could be selectively exported in Haskell, how to make it
compatible with the current assumption that they are exported by
default? Selective hiding would be weird.

Perhaps there should be a separate section for exporting instances.
If not present, then everything is exported (as with plain module
contents).

I hope selective export would help with resolving conflicting
instances. There might be a confusion if a function does indeed
get a sorted list of objects of type T but it expected a different
ordering, but the danger of inability of linking two independent
libraries due to an innocent overlapping instance might be worse.

As we are at it, it would be nice to be able to specify signatures and
other interface details where they belong - in the export list. With
a different syntax of the export list; there would be an ambiguity if
..., var1, var2 :: Type, ...
gives Type to both variables or only one, and items should be
separated by layoutable semicolons.

-- 
 __("<  Marcin Kowalczyk * [EMAIL PROTECTED] http://qrczak.ids.net.pl/
 \__/
  ^^  SYGNATURA ZASTÊPCZA
QRCZAK


___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: Are anonymous type classes the right model at all? (replying to Re: Are fundeps the right model at all?)

2000-12-25 Thread Fergus Henderson

On 21-Dec-2000, George Russell <[EMAIL PROTECTED]> wrote:
> (3) Finally it would be nice to extend the module syntax to allow named
> instances to be selectively exported and imported, just like variables.  

Mercury's module system allows instance declarations (which, as in
Haskell 98, are unnamed) to be selectively exported.

:- module foo.
:- interface.

:- import_module enum.

:- type t.
:- instance enum(t).

:- implementation.

:- instance enum(t) where [ ... ].

Mercury doesn't directly support selective import -- you can only
import a whole module, not part of it.  But if you really want that
you can achieve it by putting each instance declaration in its own
nested module.

:- module foo.
:- interface.
:- import_module enum.

   :- type t.

   :- module enum_t.
   :- interface.
   :- instance enum(t).
   :- end_module enum_t.

:- implementation.

   :- module enum_t.
   :- implementation.
   :- instance enum(t) where [ ... ].
   :- end_module enum_t.

-- 
Fergus Henderson <[EMAIL PROTECTED]>  |  "I have always known that the pursuit
|  of excellence is a lethal habit"
WWW:   | -- the last words of T. S. Garp.

___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Re: Are anonymous type classes the right model at all? (replying to Re: Are fundeps the right model at all?)

2000-12-24 Thread Marcin 'Qrczak' Kowalczyk
o = 1
> plus = (*)
> 
> data Group e = record
> monoid :: Monoid e
> minus  :: e -> e -> e
> neg:: e -> e
> monoid (zero, plus)
> x `minus` y = x `plus` neg y
> neg y   = zero `minus` y
> 
> numAddGroup :: Num e => Group e
> numAddGroup = record
> monoid  = numAddMonoid
> minus   = (-)
> neg = negate
> 
> numMulGroup :: Fractional e => Group e
> numMulGroup = record
> monoid  = numMulMonoid
> minus   = (/)
> neg = recip
> 
> data Ring e = record
> addGroup  :: Group e
> mulMonoid :: Monoid e
> addGroup  (monoid as addMonoid, zero, plus, minus, neg)
> mulMonoid (zero as one, plus as times)
> 
> numRing :: Num e => Ring e
> numRing = record
> addGroup  = numAddGroup
> mulMonoid = numMulMonoid
> 
> data Field e = record
> addGroup :: Group e
> mulGroup :: Group e
> addGroup (monoid as addMonoid, zero, plus, minus, neg)
> mulGroup (monoid as mulMonoid, zero as one, plus as times,
>minus as div, neg as recip)
> 
> instance (Field e).ring :: Ring e where
> f.ring = record
> addGroup  = f.addGroup
> mulMonoid = f.mulMonoid
> f.record {ring = r} = f.record
> addGroup  = r.addGroup
> mulMonoid = r.mulMonoid
> 
> -- Alternatively a Field could consist of a Ring and div + recip.
> -- The difference is an implementation detail not visible outside.
> -- The following definition will work with either variant:
> 
> numField :: Fractional e => Field e
> numField = record
> addGroup = numAddGroup
> mulGroup = numMulGroup

 PROBLEMS 

If those records are to simulate classes, they should be able to have
polymorphic fields. Unfortunately it does not work to have overloaded
setters in this case. I don't know a good solution.

Similarly we would want to have records with existentially quantified
types. Again it does not work to have overloaded getters and setters.

Listing all inherited fields can be annoying. It would not really
work otherwise, as arbitrary instances for sypertypes can be added
at any time. It is not necessary to list all fields: other fields
are available through the field we inherit from anyway.

It would be desirable to selectively export instances.

 PROTOTYPE IMPLEMENTATION 

I have an implementation of this in the form of a preprocessor,
based on hssource from ghc-4.11's hslibs. I will polish it and put
for downloading to let people play with my records. I hope to have
more interesting examples.

The difference between this implementation and the above proposal
is that types of inherited fields must be given explicitly. This
is because delegation instances would otherwise have to have
types which are not accepted by ghc, and they would require
-fallow-undecidable-instances if they were legal (which is not a
surprise because cyclic inheritance makes it impossible to determine
the type of the field).

I reported the problem under the subject "Problem with functional
dependencies" on December 17th. I believe that both problems can
be fixed, especially if handling those constructs were inside the
compiler.

 THE REST OF MY REPLY TO GEORGE RUSSELL 

> (1) We extend type classes to allow them to introduce types.

If your classes were expressed as my records, it would roughly
correspond to existential quantification. But there are big problems
with typechecking in this approach.

I hope somebody will invent a solution.

-- 
 __("<  Marcin Kowalczyk * [EMAIL PROTECTED] http://qrczak.ids.net.pl/
 \__/
  ^^  SYGNATURA ZASTÊPCZA
QRCZAK


___
Haskell mailing list
[EMAIL PROTECTED]
http://www.haskell.org/mailman/listinfo/haskell



Are anonymous type classes the right model at all? (replying to Re: Are fundeps the right model at all?)

2000-12-24 Thread George Russell

Alternatively, I wonder whether the current system of type classes is the right
model at all.

Although I prefer the Haskell system, I think it is instructive to compare it
with the Standard ML (SML) system of structures and functors.  My point is that
both Haskell and SML impose one of two possible extremes on the user, and
suffer for it.

With SML, it is as if all instances are explicitly named.  SML does not permit
user-defined overloading, and so SML is not capable of understanding 
something such as a "type class of things we can compare", and has a horrible
set of kludges to cope with implementing the equality operator.

With Haskell, on the other hand, there is no way of referring to a particular
instance when you want to.  We see a particular consequence of that here, in
that (unlike SML), it is not possible to associate an internal type with a 
given instance.  Another problem is that no-one has any control over what
instances get exported, because since instances are anonymous there is no way 
of referring to them.  Hence the current procedure is to expose everything to
the importer, which is surely a mistake.

So if you agree with me up to here, perhaps you are agreed that it is worth
while trying to find a middle way, in which we try to combine both approaches.
Well I'm not an expert language designer, and I'm doing this off the top of my
head late on Thursday evening, so please don't nitpick about syntax; I'm aware
that parsing will probably be difficult in all sorts of ways with exactly what
I'm writing, but that shouldn't be too hard to tweak.  In particular I have
followed SML in using "." to express qualification by something, even though
Haskell already used "." for something else, because I can't be bothered right
now to dig up a better symbol.

On the other hand if my whole approach is a pile of elephant dung I apologise
for wasting your time, and wish you a happy Christmas/holidays, but do try to
find a better way of combining the best of SML functors and Haskell classes.

Anyway here is my proposal.
(1) We extend type classes to allow them to introduce types.  Thus for example
I would replace Marcin's first example by
   class Collectible e where
  type c -- or we could just omit the "type" keyword, trading clarity
 -- for conciseness.
 --  note also that we need a way of expressing a context for
 -- "c", EG that it's an instance of Eq.
  empty :: c
  insert :: c -> e -> c
As usual, you can refer to "empty" and "insert" right away, but you 
can't refer to "c" without extra syntax.  We need a way of referring to 
the particular instance of Collectible.  So I suggest something like:

singleton :: (method | Collectible e) => e -> method.c
singleton el = insert empty el
(2) We extend instance declarations in two ways.  Firstly and obviously, we 
need a way of declaring the type c in the instance second declaration.  
The second thing is to introduce named instance declarations, like this:

instance IntList | Collectible Int where
   type c = [Int]
   empty = []
   insert = (flip(:)) 

To actually _refer_ to a specific instance, you would qualify with IntList.
So you could refer to IntList.c,  IntList.empty, IntList.insert, just like
you would with SML.  But as with Haskell, "empty" and "insert" would
continue to be available implicitly.

A more complicated example arises when you have instances depending on 
other instances.  EG

instance SetCollection | Ord el => Collectible el where
   type c = Set el
   empty = emptySet
   insert = addToSet -- new function, thank Simon Marlow

Then, in this case, you would refer to SetCollection.c when you wanted to
refer to the type c.   However note that in this case we are implicitly
using an anonymous use of Ord.  Supposing you had previously defined
(ignoring questions about overlapping instances for now . . .)

instance EccentricOrd | Ord Int where
   ...
and you wanted to define Sets in terms of EccentricOrd.  Then I suggest 
that you use instead SetCollection(EccentricOrd).c and likewise 
SetCollection(EccentricOrd).empty and Sets(EccentricOrd).insert, 
though I hope that such monstrous constructions will not often 
be necessary.   When they are, maybe it would be a good idea to allow the
user to abbreviate, as in
   instance EccentricSet | Collectible Int = SetCollection(EccentricOrd)
just as you can do in SML.
(3) Finally it would be nice to extend the module syntax to allow named
instances to be selectively exported and imported, just like variables.  
If I could ignore all pre-existing Haskell code I would specify that
whenever a module has a

Multiparameter type classes

2000-03-15 Thread Viktor Kuncak

I am writing (another) modular interpreter in Haskell (Hugs98 actually).

I keep having problems with multiparameter type classes.

Is there any sort of user's manual for this yet non-standard construct?

I understand the idea, and it is all fine when it works, but there are
many restrictions that
I do not understand. I am not sure I am ready to delve into all
implementation details to
undestand why e.g. some instance declarations are allowed and some not.

Viktor





RE: Implementation of type classes

1999-09-12 Thread Heribert Schuetz

Hi Mark,

thanks a lot for the private lesson. I have downloaded various papers
and started to read them. I'm just done with the Wadler/Blott paper.

I already suspected that I was partly reinventing the wheel with my
translation of type classes. It turned out that my approach is exactly
the same as the Wadler/Blott translation. I didn't expect my approach to
be so close to the "standard" solution, but now this gives me the good
feeling that I might have understood the stuff. In hindsight the reason
for the close similarity is of course the "user-level" understanding
that I had of type classes before.

You were mentioning rank-2 polymorphism in your message. It was exactly
that beast (and also second-order lambda calculus) that I was afraid of
when I was unsure whether my transformation does its job. I feared that
these beasts (which I don't understand yet, but hope to after working
through the pile of downloaded papers) were indispensable for type
classes. Now I see that they are not, at least for the basic case.

Regards,

Heribert.


PS: What I meant with "dependent types" were the ideas in Cayenne.





Implementation of type classes

1999-09-11 Thread Heribert Schuetz

Hello,

I'm trying to get a bit deeper understanding about how type classes are
(or could be) implemented.

At least in simple cases it seems possible to eliminate class and
instance declarations from Haskell programs. See the example below.

The idea is that for every class assertion in the type of a variable,
the variable gets an additional parameter that will be instantiated by a
value representing the appropriate instance declaration. These values
are tuples (let's call them "instance tuples") containing
- one component for every superclass (viz. an instance tuple) and
- one component for every class method (viz. a function with an
  additional argument expecting the instance tuple)

A class declaration is converted into a declaration of a type of
instance tuples.

A simple instance declaration is converted into the definition of such a
value.

An instance declaration with constraints (e.g., the Eq or the Ord
instance for lists below) is converted into a function taking one
instance tuple for each constraint and returning an instance tuple.

Now here are the questions I have:

- Does this work completely as intended or have I missed something, such
  as strictness problems or the like?

- Does this still work if more complex features of the type/class system
  are used?
  - default definitions for class methods
(This will probably work without too much effort.)
  - constructor classes
(Here I would guess the same.)
  - multi-parameter type classes
  - overlapping instances
  - existential types
  - other extensions of the class system that are, e.g., implemented in
GHC or Hugs
  - dependent types
(Perhaps here the functions returning instance tuples generated from
instance declarations must accept "normal" values and not only
instance tuples.)
  - ...

- Can the transformed program be evaluated as efficiently as the
  original one? (The original program gets an advantage if some class
  constraints are resolved at compile time. But perhaps a similar effect
  for the transformed program can be achieved with GHC's transformation
  rules.)

- Do type classes provide an advantage with respect to expressiveness of
  types? For example, can the types of an API be formulated in a more
  flexible way with classes as compared to the transformed style?

- Unless I missed something, the Haskell report lacks a description of
  the Haskell kernel except for the implicit "every language construct
  for which there is no translation given". And according to this I
  think that classes and instances belong to the kernel. With a
  translation like the one given by example below, could the need for
  classes and instances in the kernel be removed?

Most of this is probably well-known stuff and written down in papers.
Which ones? The Haskell report concentrates on the static semantics of
classes and instances. It looks like the dynamic semantics is expected
to be already understood by the reader or intuitively clear. Are the
references [6] (Jones: A system of constructor classes: overloading and
implicit higher-order polymorphism) and [11] (Wadler/Blott: How to make
ad hoc polymorphism less ad hoc) of the report available on the Web?


Thanks in advance for your hints,

Heribert.

==

Now for the example. It consists of some simplified declarations and
definitions from the prelude (marked with <) and their transformed
versions (marked with >):

--
< class Eq a where
<   (==) :: a -> a -> Bool
<
< (/=) :: Eq a => a -> a -> Bool
< x /= y = not (x==y)

> data Eq_ a = Eq_-- could be a newtype;
>   { (==-) :: a -> a -> Bool
>   }
>
> (/=-) :: Eq_ a -> a -> a -> Bool
> (/=-) eq_a x y  =  not ((==-) eq_a x y)

In order to avoid systematic name clashes with the "standard"
definitions, "-" or "_" has been appended to certain identifiers.

(BTW: Wouldn't it be nice if we could write

  x `(/=-) eq_` y  =  not (x `(==-) eq_` y)

That is, backquotes can not only be applied to varids but to arbitrary
expressions or patterns.)
--
< class (Eq a) => Ord a where
<   compare :: a -> a -> Ordering
<
< (<=) :: Ord a => a -> a -> Bool
< x <= y  =  compare x y /= GT
<
< min  :: Ord a => a -> a -> a
< min x y | x <= y =  x
< | otherwise  =  y

> data Ord_ a = Ord_
>   { eq_Ord :: Eq_ a
>   , compare_ :: a -> a -> Ordering
>   }
>
> (<=-) :: Ord_ a -> a -> a -> Bool
> (<=-) ord_a x y  =  (/=-) eq_Ordering (compare_ ord_a x y) GT
>
> min_ :: Ord_ a -> a -> a -> a
> min_ ord_a x y | (<=-) ord_a x y  =  x
>   

RE: Implementation of type classes

1999-09-11 Thread Mark P Jones

Hi Heribert,

| The idea is that for every class assertion in the type of a variable,
| the variable gets an additional parameter that will be instantiated by a
| value representing the appropriate instance declaration. These values
| are tuples (let's call them "instance tuples") containing
| - one component for every superclass (viz. an instance tuple) and
| - one component for every class method (viz. a function with an
|   additional argument expecting the instance tuple)

This is exactly the scheme proposed by Wadler and Blott in their paper
"How to make ad-hoc polymorphism less ad-hoc"!  The things that you've
called "instance tuples" here are more commonly referred to as
"dictionaries", and so the translation that is used to implement
overloading by adding these extra dictionary parameters is known as
the "dictionary passing translation".  It is also the implementation
technique used in all current Haskell compilers/interepreters, as far
as I'm aware.  I'm not particularly proud of them, and they weren't
the main topic, but you can find a couple of chapters, going into
many of the gory details of all this in my thesis (Chaps. 7 and 8, to
be precise.

[Historical aside: I did, however, produce a version of Gofer at one
stage that didn't use dictionaries: the compiler still used a
dictionary passing translation internally, but then followed that
with a specialization phase so that no dictionary values were used
at run-time.  To my initial surprise, it actually resulted in smaller
compiled programs in every example that I tried.  Two caveats: (1) the
technique doesn't work well with separate compilation, and would need
a very fancy linker; (2) the introduction of polymorphic recursion in
Haskell means that there are programs for which the technique cannot
be used.  You can read more about this in my paper on "Dictionary-free
overloading".]

| - Does this work completely as intended or have I missed something, such
|   as strictness problems or the like?

Well I hope I've dealt with all this above.  One thing to note,
however: when you add extra arguments to a variable definition, you
can end up with a function where there wasn't one before, and that
has an impact on which computations get shared, and which don't.
So it can have an impact, and that was one of the original motivations
for the "dreaded monomorphism restriction", which is still there
lurking in the definition of Haskell 98.

| - Does this still work if more complex features of the type/class system
|   are used?

Yes to all the things you listed.  (Except your last point --- "dependent
types" --- to which I'd reply that I'm not exactly sure what you were
referring to ... perhaps the kind of work that Hongwei Xi has been
doing?  Or maybe to the kinds of things that you've seen in Lennart's
Cayenne?  Or perhaps something else.)

| - Can the transformed program be evaluated as efficiently as the
|   original one? (The original program gets an advantage if some class
|   constraints are resolved at compile time. But perhaps a similar effect
|   for the transformed program can be achieved with GHC's transformation
|   rules.)

The real question here is how can the program be executed at all
*without* doing the translation.  This is one of the criticisms
that has been made of Haskell's class mechanisms, and one of the
motivations for other proposals.  You might, for example, want to
take a first look at Odersky, Wadler, and Wehr's "A second look
at overloading" to see the kind of compromises that you might need
to make and the benefits that you might hope to gain.

| - Do type classes provide an advantage with respect to expressiveness of
|   types? For example, can the types of an API be formulated in a more
|   flexible way with classes as compared to the transformed style?

They shouldn't, in theory, but along the route to Haskell, some
additional expressiveness snuck in.  Dictionary components in
Haskell, for example, can have polymorphic types (think of fmap
in the Functor class), but the components of a tuple in a regular
Haskell type cannot.  Similarly, before Haskell went official and
allowed polymorphic recursion, you could still code it up by
hacking with classes.  You can restore the balance by adding
support for rank-2 polymorphism, as is done in Hugs and GHC.
Once that's don't you don't get an extra expressiveness by programming
with type classes, but it might still make some programs seem easier
to code (because you don't have to add the extra parameters yourself).

[Historical aside 2: when constructor classes were first introduced,
several people (myself included) wrote about the "Expressiveness
of constructor classes" ... it was only later that I realized how
much of that expressiveness came from rank-2 polymorphism

Re: Implementation of type classes

1999-09-11 Thread Jan Skibinski



On Sat, 11 Sep 1999, Heribert Schuetz wrote:

> 
> Most of this is probably well-known stuff and written down in papers.
> Which ones? The Haskell report concentrates on the static semantics of
> classes and instances. It looks like the dynamic semantics is expected
> to be already understood by the reader or intuitively clear. Are the
> references [6] (Jones: A system of constructor classes: overloading and
> implicit higher-order polymorphism) and [11] (Wadler/Blott: How to make
> ad hoc polymorphism less ad hoc) of the report available on the Web?
> 

Have you read "Typing Haskell in Haskell" by Mark P.
Jones? 
(written not so long ago, available on Web and to be presented
in Haskell Workshop 1999).
It  might help you with some of your questions.

Jan
 






Re: multi param type classes

1998-07-09 Thread Fergus Henderson

On 08-Jul-1998, Mariano Suarez Alvarez <[EMAIL PROTECTED]> wrote:
> On Wed, 8 Jul 1998 [EMAIL PROTECTED] wrote:
> 
> > Each expression then has a set of possible types, and the ambiguity is   
> > resolved by an explicit type signature.
> > 
> > At present it is quite frustrating in Haskell that when a name is used in   
> > one place it is then lost for use in any other context -- the example of   
> > an overloaded size function strikes me as very sound.
> 
> I don't see why something like
> 
>   class HasSize a where
> size :: a -> Int
> 
> doesn't solve this...

Well, for one thing, that only helps with functions, not with data
constructors.  Also, not every occurrence of `size' need have type
`a -> Int', and even if they do, the `class' declaration doesn't help
unless you modify the existing uses of the name `size', which you may
not be able to do.  The point is that you often have *unrelated*
occurrences of the same name.  This is especially true if you use
unqualified imports; two modules may use the same name for entirely
different purposes.  In that situation, Haskell forces you to resolve
the issue at module import time, even if the different uses of that
name could be disambiguated by the context, and in fact even if you
don't even make use of the overloaded name at all.

-- 
Fergus Henderson <[EMAIL PROTECTED]>  |  "I have always known that the pursuit
WWW:   |  of excellence is a lethal habit"
PGP: finger [EMAIL PROTECTED]| -- the last words of T. S. Garp.





Re: multi param type classes

1998-07-09 Thread Fergus Henderson

On 08-Jul-1998, Johannes Waldmann <[EMAIL PROTECTED]> wrote:
...
> how would you resolve ambiguities?
> probably by requiring an explicit type signature
> at the point of usage.
> 
> fine, but then i'd like to have this in other cases as well,
> finally arriving at Ada-style overloading
> (a name may have several meanings
> as long as they can be distinguished by their type)
> 
> then i could write  size :: [a] -> Int; size :: Tree a -> Int,
> and the two things are completely unrelated.

FYI, the logic/functional language Mercury supports exactly that
kind of overloading.  I found the Haskell requirement that
every data constructor have a different name quite annoying:
I wound up including the type name in the data constructor names
to ensure uniqueness.  This is a pain, because you then end up
effectively type-qualifying *every* occurrence of the data constructors,
rather than only type-qualifying the ones that would otherwise be ambiguous.

-- 
Fergus Henderson <[EMAIL PROTECTED]>  |  "I have always known that the pursuit
WWW:   |  of excellence is a lethal habit"
PGP: finger [EMAIL PROTECTED]| -- the last words of T. S. Garp.





Re: multi param type classes

1998-07-08 Thread Ralf Hinze

> you want to lift this restriction:
> 
> > The type of each class operation 
> > must mention all of the class type variables.
> 
> how would you resolve ambiguities?
> probably by requiring an explicit type signature
> at the point of usage.

No longer ;-). I find SPJ's summary on

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

convincing. The point is that you simply _cannot_ resolve the ambiguity
at the point of usage. Furthermore, an alternative is at hand (for the
motivating example I gave).

Ralf





RE: multi param type classes

1998-07-08 Thread michael



I think that this is a VERY good idea!

Each expression then has a set of possible types, and the ambiguity is   
resolved by an explicit type signature.

At present it is quite frustrating in Haskell that when a name is used in   
one place it is then lost for use in any other context -- the example of   
an overloaded size function strikes me as very sound.

I would have no objection to having to declare more type annotation -- it   
seems to me that too many of the restrictions on the design of Haskell's   
type system are driven by the desire to infer too much without asking the   
user for annotations.
 I think it would be very interesting to re-visit the constraints on   
multi-parameter classes and instances in the view that the compiler may   
require type annotations on particular variables.

 --
From:  joe
Sent:  08 July 1998 15:21
To:  [EMAIL PROTECTED]; [EMAIL PROTECTED]
Subject:   Re: multi param type classes

From: Johannes Waldmann <[EMAIL PROTECTED]>
Subject: Re: multi param type classes
To: [EMAIL PROTECTED]

Ralf,

you want to lift this restriction:

> The type of each class operation
> must mention all of the class type variables.

how would you resolve ambiguities?
probably by requiring an explicit type signature
at the point of usage.

fine, but then i'd like to have this in other cases as well,
finally arriving at Ada-style overloading
(a name may have several meanings
as long as they can be distinguished by their type)

then i could write  size :: [a] -> Int; size :: Tree a -> Int,
and the two things are completely unrelated.
at the moment, i could make [] and Tree an instance
of a class that has `size' as a method (feels clumsy)
or write sizeList and sizeTree (feels bad as well:
what is part of the name here is really a type signature).

of course this would break the general Haskell idea
that every expression has a unique type
that can be reconstructed by the compiler.
but this is broken anyway (you need type annotations here and there),
and is it a good design goal?

why would you want it? for easier compilation?
for easier programming? an Haskell where i'd have to declare
the type for some, or even each, let-bound variable
doesn't feel that horrendous to me. plenty of other languages
require typed declarations.

best regards,
 --
Dr Johannes Waldmann  Institut fur InformatikUniversitat Leipzig   


[EMAIL PROTECTED] http://www.informatik.uni-leipzig.de/~joe/
PF 920,  D-04009  Leipzig,  Germany   Tel/Fax (+49) 341 97 32204 / 32209






Re: multi param type classes

1998-07-08 Thread Johannes Waldmann

Ralf, 

you want to lift this restriction:

> The type of each class operation 
> must mention all of the class type variables.

how would you resolve ambiguities?
probably by requiring an explicit type signature
at the point of usage.

fine, but then i'd like to have this in other cases as well,
finally arriving at Ada-style overloading
(a name may have several meanings
as long as they can be distinguished by their type)

then i could write  size :: [a] -> Int; size :: Tree a -> Int,
and the two things are completely unrelated.
at the moment, i could make [] and Tree an instance
of a class that has `size' as a method (feels clumsy)
or write sizeList and sizeTree (feels bad as well:
what is part of the name here is really a type signature).

of course this would break the general Haskell idea
that every expression has a unique type 
that can be reconstructed by the compiler.
but this is broken anyway (you need type annotations here and there),
and is it a good design goal?

why would you want it? for easier compilation?
for easier programming? an Haskell where i'd have to declare
the type for some, or even each, let-bound variable
doesn't feel that horrendous to me. plenty of other languages
require typed declarations.

best regards,
-- 
Dr Johannes Waldmann  Institut fur InformatikUniversitat Leipzig   
[EMAIL PROTECTED] http://www.informatik.uni-leipzig.de/~joe/
PF 920,  D-04009  Leipzig,  Germany   Tel/Fax (+49) 341 97 32204 / 32209






RE: multi param type classes

1998-07-08 Thread Mariano Suarez Alvarez

On Wed, 8 Jul 1998 [EMAIL PROTECTED] wrote:

> Each expression then has a set of possible types, and the ambiguity is   
> resolved by an explicit type signature.
> 
> At present it is quite frustrating in Haskell that when a name is used in   
> one place it is then lost for use in any other context -- the example of   
> an overloaded size function strikes me as very sound.

I don't see why something like

class HasSize a where
  size :: a -> Int

doesn't solve this...

-- m

---
Mariano Suarez Alvarez
Departamento de Matematica  
Universidad Nacional de Rosario
Pellegrini 250
2000 Rosario - Argentina 
e-mail: [EMAIL PROTECTED]
---

El autor no responde de las molestias que puedan ocasionar sus escritos:
Aunque le pese
El lector tendra que darse siempre por satisfecho.

Nicanor Parra, `Poemas y antipoemas' (Advertencia al lector)

---






Re: multi param type classes

1998-07-08 Thread S. Alexander Jacobson

I think Simon or Alastair promised this in 2.0 (though it doesn't appear
on the list for 2.0...)

-Alex-

On Thu, 9 Jul 1998, Fergus Henderson wrote:

> On 08-Jul-1998, Johannes Waldmann <[EMAIL PROTECTED]> wrote:
> ...
> > how would you resolve ambiguities?
> > probably by requiring an explicit type signature
> > at the point of usage.
> > 
> > fine, but then i'd like to have this in other cases as well,
> > finally arriving at Ada-style overloading
> > (a name may have several meanings
> > as long as they can be distinguished by their type)
> > 
> > then i could write  size :: [a] -> Int; size :: Tree a -> Int,
> > and the two things are completely unrelated.
> 
> FYI, the logic/functional language Mercury supports exactly that
> kind of overloading.  I found the Haskell requirement that
> every data constructor have a different name quite annoying:
> I wound up including the type name in the data constructor names
> to ensure uniqueness.  This is a pain, because you then end up
> effectively type-qualifying *every* occurrence of the data constructors,
> rather than only type-qualifying the ones that would otherwise be ambiguous.
> 
> -- 
> Fergus Henderson <[EMAIL PROTECTED]>  |  "I have always known that the pursuit
> WWW:   |  of excellence is a lethal habit"
> PGP: finger [EMAIL PROTECTED]| -- the last words of T. S. Garp.
> 

___
S. Alexander Jacobson   i2x Media  
1-212-697-0184 voice1-212-697-1427 fax






Re: Multi-parameter type classes

1998-07-02 Thread Fergus Henderson

In ,
Simon L Peyton Jones <[EMAIL PROTECTED]> wrote:

 |5. In the signature of a class operation, every constraint must
 |   mention at least one type variable that is not a class type
 |   variable. Thus:
 ...
 |   > class C a where
 |   >op :: Eq a => (a,b) -> (a,b)
 |
 |   is not OK because the constraint (Eq a) mentions on the class type
 |   variable a, and no others.

What's the rationale for this rule?

 |   (GHC 3.02 enforces a more restrictive rule, but that's definitely
 |   wrong.)
 |   A yet more relaxed rule would allow the context of a class-op
 |   signature to mention only class type variables. I don't like that
 |   from an implementation point of view;

Could you be more specific?  What's the implementation difficulty?

-- 
Fergus Henderson <[EMAIL PROTECTED]>  |  "I have always known that the pursuit
WWW:   |  of excellence is a lethal habit"
PGP: finger [EMAIL PROTECTED]| -- the last words of T. S. Garp.





Re: Multi-parameter type classes

1998-07-01 Thread Simon L Peyton Jones

>  |5. In the signature of a class operation, every constraint must
>  |   mention at least one type variable that is not a class type
>  |   variable. Thus:
>  ...
>  |   > class C a where
>  |   >op :: Eq a => (a,b) -> (a,b)
>  |
>  |   is not OK because the constraint (Eq a) mentions on the class type
>  |   variable a, and no others.
> 
> What's the rationale for this rule?

It's hard to explain (which may well mean my head is on backwards).
In the 5 mins I have today here's what I added to the document


The reason it's awkward to implement is this. Supose you
are type checking the RHS of op in an instance declaration for C 
[c],
and suppose you have found that you need the constraint (C (S c)).
Should we reduce the constraint, in the hope being able to
"use" the Eq [c] we have available?  Or should we just
postpone this reduction for the top level of the class decl. 
Usually I make this decision based on whether the constraint mentions any
of the universally quantified type variables (b in this case),
which it doesn't.  Without this convenient test I have to either
to eager context reduction (which I don't want to do), or some sort
of search strategy.

Simon





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






  1   2   >