There is a problem with operators like +, - and * which are both infix and prefix. When you write
a - b the parser knows you mean infix. But what about: - (a,b) Is this the prefix operator applied to pair, or is it the infix operator? Normally you wouldn't define an single argument operator on a tuple, so if you write: fun - (a:int) => .. // negative of a fun - (a:int, b:int) => .. // subtraction it's all clear. We actually have two functions here named "-" which overload on a single argument, of types: int and int * int So everything works .. until you get to type classes. Then it all falls apart. Consider: class X[T] { fun - (a:T) => .. fun - (a:T,b:T) => ... } open[K] X[K]; var x = - (1,1); // WOOPS! The open statement makes fun -[T] : T -> ... // T = int * int fun -[T] : T * T .. // T = int visible and so the call is ambiguous. Even if you write: - of (int * int) (1,1) it doesn't help because both specialisations lead to that signature. This problem cannot happen in a type class itself, because T inside the class is not a type variable: it is existentially quantified not universally quantified internally, which means it is just an unknown abstract type, not a variable. That's the difference between classes and modules. In particular: class X { fun -[T] (a:T) => .. fun -[T] (a:T,b:T) => .. is NOT the same as the original class X I showed. This class is a module, it isn't polymorphic, the individual functions are universally quantified, that is, they're polymorphic. In the former case the whole class is universally quantified and polymorphic but the individual functions are monomorphic. For them T is just a single unknown type, the same T everywhere. However when you do: open[K] X[K]; you're making all classes X with parameter K available, which means all specialisations of the functions. Which ensures all calls to operator - with a pair argument are ambiguous. You may never have seen such an open statement .. but this one is syntactic sugar for it, and is equivalent: open X; The moral of the story is: do NOT use the same operator name to define a prefix and infix function. Now, this does NOT mean we cannot write - 1 and 1 - 1 and have it work. The parser knows which function it is. But it generates -1 and - (1,1) at the moment. In the old days, operator symbols couldn't be function names. Instead we had class X [T] { fun neg (a:T) => ... fun add (a:T,b:T) => .. that is, the names were distinguished. The problem there was you had to KNOW the mapping made by the parser. You had to know prefix * mapped to a function named "deref". So I allowed operator names as identifiers and changed the parser and thus dug myself into a hole. I could got back to "neg". Another solution is: prefix - (a:int) => .... infix - (a:int, b:int) => Another tricker solution: fun (a:int) - (b:int) => ... although I can't see how this fits with the grammar for lambdas or C++ bindings. It's almost possible to do this: fun (a:int) - (b:int) / (c:int) => ... i.e. provide a pattern. This is, after all, exactly what reduce does. The only trick is that reductions aren't guaranteed to be provided. Still .. it looks really cool! -- john skaller skal...@users.sourceforge.net http://felix-lang.org ------------------------------------------------------------------------------ Want excitement? Manually upgrade your production database. When you want reliability, choose Perforce Perforce version control. Predictably reliable. http://pubads.g.doubleclick.net/gampad/clk?id=157508191&iu=/4140/ostg.clktrk _______________________________________________ Felix-language mailing list Felix-language@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/felix-language