Specializing classes with classes

Hi, I am new to everything Haskell and am stumped on an aspect of Type Classes. I would like to do this: class Foo t where hi :: t -> Bool class Foo t => Bar t where hi x = True But using GHC 6.8.1 on PPC I get this error: `hi' is not a (visible) method of class `Bar' The actual problem is more like this: class Num a => Alg a where (<>) :: Mat m => m -> a -> a -- matrix multiply class Alg v => Vec v where toRow, toColumn :: Mat m => v -> m fromRow, fromColumn :: Mat m => m -> v fromRow = fromColumn . transpose toRow = transpose . toColumn (<>) m v = fromColumn (m <> (toColumn v)) class Alg m => Mat m where transpose :: m -> m (I hope that's readable...) I'm having trouble finding what I need with Google, and SOE doesn't really go into specifics. Thanks for any help... Alex Make the switch to the world's best email. Get the new Yahoo!7 Mail now. www.yahoo7.com.au/worldsbestemail

G'day all.
Quoting alex
I would like to do this:
class Foo t where hi :: t -> Bool
class Foo t => Bar t where hi x = True
This is arguably one of the most requested features in Haskell. The only reason why it hasn't been implemented yet is that some of the corner cases are a little subtle. But this will get fixed, won't it, haskell-prime people? What you'll have to do until then is something like this: class Num a => Alg a where (<>) :: Mat m => m -> a -> a multByVec :: (Vec v, Mat m) => m -> a -> a multByVec m v = fromColumn (m <> toColumn v) class Alg v => Vec v where toRow, toColumn :: Mat m => v -> m fromRow, fromColumn :: Mat m => m -> v fromRow = fromColumn . transpose toRow = transpose . toColumn class Alg m => Mat m where transpose :: m -> m class Alg SomeType where (<>) = multByVec class Vec SomeType where toRow = {- etc etc -} {- and so on -} Sorry, I wish there was a better answer. Cheers, Andrew Bromage

I see.. (Presumably you meant "instance Alg Sometype", "instance Vec Sometype" etc.) I have got it working now, and it looks like: 1) I can't specialise superclass methods with other class methods, within the class hierarchy, and 2) I have to instantiate each superclass individually, for any type. ...which is consistent with what you were saying. Thanks for clearing that up. Now I know what they meant what they meant by "leave your OO at the door". --- ajb@spamcop.net wrote: ...
What you'll have to do until then is something like this:
class Num a => Alg a where (<>) :: Mat m => m -> a -> a
multByVec :: (Vec v, Mat m) => m -> a -> a multByVec m v = fromColumn (m <> toColumn v)
class Alg v => Vec v where toRow, toColumn :: Mat m => v -> m fromRow, fromColumn :: Mat m => m -> v
fromRow = fromColumn . transpose toRow = transpose . toColumn
class Alg m => Mat m where transpose :: m -> m
class Alg SomeType where (<>) = multByVec
class Vec SomeType where toRow = {- etc etc -} {- and so on -}
Sorry, I wish there was a better answer.
Cheers, Andrew Bromage _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Make the switch to the world's best email. Get the new Yahoo!7 Mail now. www.yahoo7.com.au/worldsbestemail

G'day all.
Quoting alex
(Presumably you meant "instance Alg Sometype", "instance Vec Sometype" etc.)
Yes, most likely. Obviously I didn't try to compile the code.
Now I know what they meant what they meant by "leave your OO at the door".
To be fair, Haskell typeclasses are no less OO than DCOM or CORBA, and have similar limitations. Haskell gives you interface inheritance, with a couple of things that were easy to implement to make your life a bit easier. And, of course, the inability to declare a subclass and get the superclass instances for free is considered by pretty much everyone to be a limitation which will be fixed, once the tricky cases are worked out. Cheers, Andrew Bromage

On Dec 28, 2007, at 10:18 PM, ajb@spamcop.net wrote:
Quoting alex
: I would like to do this:
class Foo t where hi :: t -> Bool
class Foo t => Bar t where hi x = True
This is arguably one of the most requested features in Haskell. The only reason why it hasn't been implemented yet is that some of the corner cases are a little subtle.
Really? This code doesn't even really make any sense to me. In order to be an instance of Bar, t has to already be an instance of Foo, implying that the function hi is already defined for t. What would the function in this example do? instance Foo Wibble where hi x = False instance Bar Wibble myFunc :: Wibble -> Bool myFunc x = hi x

On Dec 30, 2007 2:43 PM, Jake McArthur
Really? This code doesn't even really make any sense to me. In order to be an instance of Bar, t has to already be an instance of Foo, implying that the function hi is already defined for t. What would the function in this example do?
Here's a different example: class Functor f where fmap :: (a -> b) -> f a -> f b class (Functor m) => Monad m where (>>=) :: m a -> (a -> m b) -> m b return :: a -> m a fmap = liftM In this case, any instance of Monad would automatically get a default Functor instance, which could presumably be overridden by an explicit Functor instance. The point is that (by default) you don't have to give the definition of *fmap* yourself. As AJB pointed out, the details can be subtle, so this sort of thing hasn't been implemented by anybody as far as I'm aware. Stuart

alex wrote:
Hi, I am new to everything Haskell and am stumped on an aspect of Type Classes.
I would like to do this:
class Foo t where hi :: t -> Bool
class Foo t => Bar t where hi x = True
But using GHC 6.8.1 on PPC I get this error:
`hi' is not a (visible) method of class `Bar'
You can't do that. (Well, you just discovered that!) When you say "class Foo t => Bar t", what you're saying is that no type can belong to "Bar" until it belongs to "Foo" first. And that is all. Remember, in Haskell any given type can belong to any number of classes all at once. All the definition there says is that you have to add a type to Foo before you can add it to Bar. You still have to write two [seperate] instance declarations. It's not like OOP where every Bar *is* a Foo. They remain seperate. You just need to have one before you can have the other. Beyond that, they share nothing. [Well, the default methods for Bar can mention methods in Foo. But that's about it.] One might hope, for example, that you could define a "Vector" class, and make it so that anything that is a member of Vector is automatically a member of Num. Sadly, this is impossible. Even if each instance declaration is identical but for the type names, you must still write out each definition seperately. Pitty...
participants (5)
-
ajb@spamcop.net
-
alex
-
Andrew Coppin
-
Jake McArthur
-
Stuart Cook