
Hello, I'm trying to understand classes and defined: class Monoid a where e :: a add :: a -> a -> a add a e = a add e a = a instance Monoid a Int where e = 0 add x y = x + y This works just fine, also for instance definitions of Char, Bool and lists. But defining: class (Num a, Monoid a) => NumMon a where e = 0 add x y = x + y reults in error messages. -- Hugs: ERROR "Chap12.hs":57 - No member "e" in class "NumMon" -- GHCi: Chap12.hs:58:3: `add' is not a (visible) method of class NumMon' I've also tried instance definitions of NumMon (leaving out 'where' and what's next in the class declaration) and get similar messages. The definition of NumMon by itself, just the first line, is accepted by Hugs and GHCi both. What am I doing wrong? Many thanks in advance. Hans van Thiel

On Sun, Jan 21, 2007 at 06:21:34PM +0100, Hans van Thiel wrote:
class (Num a, Monoid a) => NumMon a where e = 0 add x y = x + y
What am I doing wrong? Many thanks in advance.
Nothing! What you are trying to do, declare a class B containing all members of a class A, is simply not supported in Haskell. This is the closest you'll get with Haskell98:
newtype Wrap a = Wrap (Wrap a) instance Num a => Monoid (Wrap a) where e = Wrap 0 add (Wrap x) (Wrap y) = Wrap (x + y)
This is the closest you'll get with GHC extensions:
{-# OPTIONS_GHC -fallow-undecidable-instances #-} instance Num a => Monoid a where e = 0 add = (+)
Hope this helps.

On Sun, 2007-01-21 at 09:42 -0800, Stefan O'Rear wrote:
On Sun, Jan 21, 2007 at 06:21:34PM +0100, Hans van Thiel wrote:
class (Num a, Monoid a) => NumMon a where e = 0 add x y = x + y
What am I doing wrong? Many thanks in advance.
Nothing!
What you are trying to do, declare a class B containing all members of a class A, is simply not supported in Haskell.
This is the closest you'll get with Haskell98:
newtype Wrap a = Wrap (Wrap a) instance Num a => Monoid (Wrap a) where e = Wrap 0 add (Wrap x) (Wrap y) = Wrap (x + y)
This is the closest you'll get with GHC extensions:
{-# OPTIONS_GHC -fallow-undecidable-instances #-} instance Num a => Monoid a where e = 0 add = (+)
Hope this helps. Yes, thank you. The one with the gHC extension looks like what I wanted to do, but then in reverse order, declare the numbers to be monoids. Expanding on this, I've now got:
class Monoid a => Group a where inv :: a -> a minus :: a-> a -> a minus x y = add x (inv y) inv x = minus e x instance Group Int where minus = flip subtract -- inv x = -x This seems to work. What I like is that, like in EQ and Ord, functions are defined in several ways by default. So, for Int, you can choose to define either inv or minus, you don't have to do both. But subtract and - are defined over all types of Num, so it would be nice to have something like instance Group a => Num a where ..... I understand this cannot be done in Haskell98, but it can with the GHC extension? Does {-# OPTIONS_GHC -fallow-undecidable-instances #-} refer to possibly infinite definitions? Thanks again! Hans van Thiel

On Sun, Jan 21, 2007 at 08:00:53PM +0100, Hans van Thiel wrote:
On Sun, 2007-01-21 at 09:42 -0800, Stefan O'Rear wrote:
This is the closest you'll get with GHC extensions:
{-# OPTIONS_GHC -fallow-undecidable-instances #-} instance Num a => Monoid a where e = 0 add = (+)
Yes, thank you. The one with the gHC extension looks like what I wanted to do, but then in reverse order, declare the numbers to be monoids. Expanding on this, I've now got:
In an instance definition, the => is implication; a number is a monoid if it is a number. (Yes, we know the class syntax is backward :( )
class Monoid a => Group a where inv :: a -> a minus :: a-> a -> a minus x y = add x (inv y) inv x = minus e x
instance Group Int where minus = flip subtract -- inv x = -x
This seems to work. What I like is that, like in EQ and Ord, functions are defined in several ways by default. So, for Int, you can choose to define either inv or minus, you don't have to do both.
looks correct
But subtract and - are defined over all types of Num, so it would be nice to have something like
instance Group a => Num a where .....
I understand this cannot be done in Haskell98, but it can with the GHC extension? Does {-# OPTIONS_GHC -fallow-undecidable-instances #-} refer to possibly infinite definitions? Thanks again!
Almost - that instance definition says that every group is a number (~= ring), which probably isn't what you meant :) instance Num a => Group a where ..... Haskell instance definitions, unrestricted, effectively force the compiler to solve arbitrary logic problems, which can take up to and including forever. To keep type inference terminating, H98 imposes a number of severe restrictions. GHC has a number of options to relax the restrictions in ways that complicate typechecking but don't make it impossible (-fallow-overlapping-instances, etc); -fallow-undecidable-instances is the ultimate flag and basically says "Do what I say - I accept responsibility if the typechecker goes into an infinite loop". Keep SIGINT handy.

I. On Sun, 2007-01-21 at 11:20 -0800, Stefan O'Rear wrote:
On Sun, Jan 21, 2007 at 08:00:53PM +0100, Hans van Thiel wrote:
On Sun, 2007-01-21 at 09:42 -0800, Stefan O'Rear wrote:
This is the closest you'll get with GHC extensions:
{-# OPTIONS_GHC -fallow-undecidable-instances #-} instance Num a => Monoid a where e = 0 add = (+)
Yes, thank you. The one with the gHC extension looks like what I wanted to do, but then in reverse order, declare the numbers to be monoids. Expanding on this, I've now got:
In an instance definition, the => is implication; a number is a monoid if it is a number. (Yes, we know the class syntax is backward :( ) Thanks for pointing this out. :-)
class Monoid a => Group a where inv :: a -> a minus :: a-> a -> a minus x y = add x (inv y) inv x = minus e x
instance Group Int where minus = flip subtract -- inv x = -x
This seems to work. What I like is that, like in EQ and Ord, functions are defined in several ways by default. So, for Int, you can choose to define either inv or minus, you don't have to do both.
looks correct
But subtract and - are defined over all types of Num, so it would be nice to have something like
instance Group a => Num a where .....
I understand this cannot be done in Haskell98, but it can with the GHC extension? Does {-# OPTIONS_GHC -fallow-undecidable-instances #-} refer to possibly infinite definitions? Thanks again!
Almost - that instance definition says that every group is a number (~= ring), which probably isn't what you meant :) As above, useful to know :-)
instance Num a => Group a where .....
Haskell instance definitions, unrestricted, effectively force the compiler to solve arbitrary logic problems, which can take up to and including forever. To keep type inference terminating, H98 imposes a number of severe restrictions. GHC has a number of options to relax the restrictions in ways that complicate typechecking but don't make it impossible (-fallow-overlapping-instances, etc); -fallow-undecidable-instances is the ultimate flag and basically says "Do what I say - I accept responsibility if the typechecker goes into an infinite loop".
Keep SIGINT handy. It's pretty clear now, thanks for the help!

Hello Hans, Sunday, January 21, 2007, 10:00:53 PM, you wrote:
I understand this cannot be done in Haskell98, but it can with the GHC extension? Does {-# OPTIONS_GHC -fallow-undecidable-instances #-} refer to possibly infinite definitions? Thanks again!
as usual i suggest you to read http://haskell.org/haskellwiki/OOP_vs_type_classes in order to grok type classes when i have likewise problems in my Streams library, i've finally finished with approach where bodies of default definitions are written as ordinal functions and i just call these bodies explicitly when defining instances of my classes. believe me, it's best one can do without selling his soul to Oleg :) -- Best regards, Bulat mailto:Bulat.Ziganshin@gmail.com
participants (3)
-
Bulat Ziganshin
-
Hans van Thiel
-
Stefan O'Rear