On Mon, 2007-10-01 at 15:30 -0700, Erick Tryzelaar wrote:
> I noticed that with the list instance of Str doesn't need to open the
> instance to have it be usable, as shown in this example:
> 
> val x = List::list (1, 2, 3);
> println $ x;
> 
> (btw, I love not having to import flx.flxh :) )
> 
> Did something change that we no longer have to open instances for some
> types of types, or did it always work?

You can't open instances .. that's always been a confusion for you.
You can only open specialisations of typeclasses. 

The instances are irrelevant until the instantiator looks for them,
and it finds them no matter where they're defined: instances are
global in that sense, however where they're defined does matter
because it determines the scope in which they're bound (lookup
done).

Anyhow, I think (LOL!) it works like this: here is println:

  proc println[T with Str[T]] (x:T) { 
        fprint (cout, str x);
        endl cout; 
  };


Now, println itself is 'opening Str[T]' for ALL T.
For this to work, Str must be in scope, but that is all.
This function is implemented (literally) as:

  proc println[T] (x:T) { 
        open Str[T];
        fprint (cout, str x);
        endl cout; 
  };

so you can see, it really DOES open Str, for all values of T
it is called with. That's all that 'with Str[T]' does: it opens
Str[T] in the scope of the function. [More precisely,
it opens it BEFORE the parameter list, otherwise 'open'
in the body would be good enough .. but then, in case you
didn't know, Felix binds parameters in the SAME scope as
the function body.. hehe!]

This would work too:

        open[T] Str[T]; // for all T, open Str[T]
        proc println[Y] (x:Y) {
                fprint (cout, str x);
                endl cout;
        }

because now Str[Y] is available by substitution T->Y.
But if you did this, it wouldn't work:

        open Str[int];
        ...

even if you try to print an integer, because the function
has to be bound first.

So typeclasses cheat. You should think of typeclasses as
templates, and instances as specialisations. The template
is polymorphic .. but it fails at instantiation time (link
time) if there is no instance defined somewhere.

The main difference is Felix does not allow dependent name
lookup so you cannot use overloading: instead, the binding
is like fully parametric polymorphism with 'overloading'
deferred.

Haskell does this at run time by passing a dictionary
(effectively a vtable) but Felix instantiates at
compile time so the result is guaranteed to be inline-able
and thus very fast.

-- 
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Felix-language mailing list
Felix-language@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/felix-language

Reply via email to