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