
On Wed, Jan 20, 2016, at 02:25, Simon Peyton Jones wrote:
| > undefined :: AppendsCallStack => a | | Seems simpler. Is it problems with a nullary class?
Hmm. Actually I think that's quite a good idea.
I agree, this is much nicer than enabling ImplicitParams and having to remember the naming convention! However, it seems to me that we could implement this as a constraint synonym (pending Joachim's bug #11466). So the main benefit from giving CallStack its own class would be in simplifying the implementation.
There are disadvantages:
* The special cases in the type checker need a 2-level pattern match: for the magic "IP" class, and then the magic "CallStack" type
I don't think this is so bad, we already have a function isCallStackCt that encapsulates the logic.
* In principle you might have multiple call stacks kicking around at the same time boo :: (?a::CallStack, ?b::CallStack) => Int -> Int Now I'm not really sure what is supposed to happen about solving these constraints. Perhaps it could be a feature, but it's not one anyone has asked for, and even having to think about it makes my head hurt.
Ugh, I don't want to think about this either.
Your alternative suggestion is to have a magic nullary class, the ICallStack class ("I" for implicit) so that
class ICallStack where callStack :: CallStack
At least that's is the implementation, but all the user can see is the overloaded function
callStack :: ICallStack => CallStack
The solving rules, the CallStack type, and functions for printing it, would be precisely as now.
I like this. What about others?
I think there's a problem with this approach. The new ability to freeze CallStacks relies on being able to construct new dictionaries on-the-fly for ImplicitParams. So if we were to re-implement CallStacks with their own class, we would have to copy the shadowing logic that we already have for ImplicitParams. So I'm in favor of Joachim's constraint synonym. Eric