Type classes and code generation

Bayley, Alistair Alistair_Bayley@ldn.invesco.com
Tue, 17 Jun 2003 14:02:19 +0100


> > 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.
*****************************************************************