
Hi, I am studying the Haskell type class system as part of a language comparison thesis. At this point I am looking at how default function definitions are handled in classes. Functions are usually defined in instances, not classes. I appreciate that the code below may not be an appropriate way to write Haskell programs, but it does help me understand how defaults work. I am not trying to construct a running program. Any feedback on the questions below and defaults work in general would be appreciated. Pat module A where data Person = Person String Integer deriving Show data Employee = Employee String Integer deriving Show class C1 c1 where age :: c1 -> Integer -- add default impl, can this be defined only once at class level? -- Can this function be redefined in a *class* lower down the heirarchy? age(c1) = 1 -- Is it true that instances must exists before we can run function or make subclasses? instance C1 Person where instance C1 Employee where -- Is it true that C2 can inherit age, provided an instance of C1 exists class C1 c2 => C2 c2 where name :: c2 -> String name(c2) = "C2" instance C2 Person where instance C2 Employee where -- Is it true that C3 cannot override C1 or C2 existing defaults? -- Is it true that this must be done at instance level? -- class Cx c3 => C3 c3 where -- age(c3) = 3 -- This message has been scanned for content and viruses by the DIT Information Services E-Mail Scanning Service, and is believed to be clean. http://www.dit.ie

On Saturday 24 July 2010 19:59:26, Patrick Browne wrote:
module A where data Person = Person String Integer deriving Show data Employee = Employee String Integer deriving Show
class C1 c1 where age :: c1 -> Integer -- add default impl, can this be defined only once at class level? -- Can this function be redefined in a *class* lower down the heirarchy? age(c1) = 1
That would normally be written age _ = 1 Yes, a default implementation of a class method can only be given in the class definition, it can't be redefined, but it can be overridden in an instance declaration. For example instance C1 Person where age _ = 3 instance C1 Employee where age (Employee _ n) = n
-- Is it true that instances must exists before we can run function or make subclasses? instance C1 Person where instance C1 Employee where
You can *call* class methods only for types which are instances of that class. You can define "subclasses" [not to confuse with OO-subclasses] of C1 even if there are no instances of C1 in scope.
-- Is it true that C2 can inherit age, provided an instance of C1 exists class C1 c2 => C2 c2 where name :: c2 -> String name(c2) = "C2"
A compiler/interpreter can accept an instance declaration of C2 for a type only if an instance of C1 for that type in scope [defined in the same module or in a module directly or indirectly imported; class instances are always re-exported from a module]. Since an instance of C2 must also be an instance of C1, all methods of C1 can be applied to that type.
instance C2 Person where instance C2 Employee where
-- Is it true that C3 cannot override C1 or C2 existing defaults? -- Is it true that this must be done at instance level? -- class Cx c3 => C3 c3 where -- age(c3) = 3 --
True. Default methods can only be overridden in instance declarations for the class.

-- Is it true that instances must exists before we can run function or make subclasses? instance C1 Person where instance C1 Employee where
You can *call* class methods only for types which are instances of that class.
But you can certain *write* functions that make use of the class methods, even if no instances exist, provided they remain polymorphic over the class. e.g. cumulativeAges :: C1 a => [a] -> Integer cumulativeAges = sum . map age The assumption would be that some client of your code would eventually need to declare at least one instance, for some type they are interested in, before they could use the function at that concrete type. Those instances need not be in the same module as the definition of the class, nor in the same module as function definitions like cumulativeAges. Regards, Malcolm

On Jul 24, 2010, at 10:59 AM, Patrick Browne wrote:
class C1 c1 where age :: c1 -> Integer -- add default impl, can this be defined only once at class level? -- Can this function be redefined in a *class* lower down the heirarchy? age(c1) = 1
Yes, but keep in mind that the hierarchy is only two levels tall. This mechanism isn't meant for OO-style inheritance.
-- Is it true that instances must exists before we can run function or make subclasses? instance C1 Person where instance C1 Employee where
Yes, absolutely.
-- Is it true that C2 can inherit age, provided an instance of C1 exists class C1 c2 => C2 c2 where name :: c2 -> String name(c2) = "C2"
instance C2 Person where instance C2 Employee where
There's no notion of "inheritance" here. If Person belongs to C2, then it "must" belong to C1, because you have specifically said that a C2 needs to be a C1 (presumably because you need a person's age to compute their name). So Person will be using C1's "age" function, in virtue of having a C1 instance. Compare this to: class C4 c4 where name' :: c4 -> String instance C1 Person -- gives Person an age function, either default or overridden instance C1 thing => C4 thing -- gives every C1 thing a name, needs Haskell extensions.
-- Is it true that C3 cannot override C1 or C2 existing defaults? -- Is it true that this must be done at instance level? -- class Cx c3 => C3 c3 where -- age(c3) = 3
Yes, as I said, the hierarchy is two levels tall.

Patrick Browne wrote:
Hi, I am studying the Haskell type class system as part of a language comparison thesis. At this point I am looking at how default function definitions are handled in classes. Functions are usually defined in instances, not classes. I appreciate that the code below may not be an appropriate way to write Haskell programs, but it does help me understand how defaults work. I am not trying to construct a running program. Any feedback on the questions below and defaults work in general would be appreciated.
1. Stop thinking of Haskell "classes" being like normal classes in OOP. They are more like what Java calls "interfaces". A type can belong to a class, much like in Java any class can implement Runnable (for example). 2. Making one class a "subclass" of another merely means that before a type can be made an instance of Y, it must first be an instance of X. There is no "inheritance" in Haskell. And no, if Y is a subclass of X, it cannot change anything in X, just add new stuff. It merely means that if you say "I want something that's an instance of Y" then it's also guaranteed to be an instance of X, without you having to manually say so. 3. A default implementation is just what it says on the tin: an implementation that will automatically be used if you don't manually supply one. The usual reason for this is if there's an implementation that will always work, but in some cases there may be a more efficient one. The default implementation is then the general version that will always work, and when you write instances for other types, you may specify a better implementation. The other reason is if X can be defined in terms of Y, and Y can be defined in terms of X. Add default implementations for both, and when you write an instance you can implement whichever one is easiest and use the default for the other. HTH.
participants (5)
-
Alexander Solla
-
Andrew Coppin
-
Daniel Fischer
-
Malcolm Wallace
-
Patrick Browne