
I thought about this issue a little more, and I think I see clearer now. Usually, you can reference a function in two ways: * apply f to an argument: f x * pass f as a first-class object: f A function taking an implicit parameter (let's call them IP functions for brevity) is applied to the (invisible) parameter as soon as you write its name, so we are only left with one option: * apply f to an argument: f * pass f as a first-class object: [not possible] This explains why my idea to collect controller functions in a list - Haskell doesn't offer a syntax to talk about an "unapplied" IP function. Can we change that? There are two possible ways: a) Let the compiler figure out whether a mention of an IP function is meant to be an application or just a reference. This approach can probably be dismissed right away because the only condition to distinguish the two variants that I can imagine is whether the caller's context contains the required implicit parameter. This, in turn, is only decidable if the current function has a type signature. We clearly cannot require a mandatory type signature for all functions using implicit parameters. b) Introduce a syntax for deferring appliation of IP functions, e.g.: * apply f to an argument: f * pass f as a first-class object: ??f If an unapplied IP function such as ??f is passed to another function, depending on how that function references it - with ?? or without -, either the implicit parameter is finally applied or its application is being deferred once again. This might have problematic implications on the type system; I'm not sure if it could handle unapplied IP functions being freely moved around. Hm. It seems to me that implicit parameters are somewhat at odds with functional programming spirit. In a way, IP functions are more like macros than like first-class functions. They also tend to blur referential transparency. They should probably be used sparingly and with care. -Stefan Stefan Reich wrote:
Hi,
I discovered implicit parameters today and I'm very excited about them because they allow to express certain code constructs more elegantly. However, I stumbled upon a problem. Suppose I have these definitions (the definition of Request is irrelevant):
type Controller = (?req :: Request) => String
controller1 :: Controller controller2 :: Controller
controllerList = [controller1, controller2]
GHC complains with:
Unbound implicit parameter (?req :: Request) arising from use of `controller1' In the list element: controller1 In the definition of `controllerList': controllerList = [controller1, controller2]
I can see why this isn't allowed; controllerList requires an implicit parameter ?req because it references functions needing this parameter. But I want it to be parameterless - it's just a static list of controller functions after all. The actual request shouldn't be supplied when selecting a controller from the list, but rather later, when invoking it.
A solution is to make the parameter explicit by binding it:
controllerList = [\req -> let ?req = req in controller1, \req -> let ?req = req in controller2]
This works, but can't really be called elegant (the binding has to be repeated for every controller). So I tried to at least move the rebinding into a function:
explicitRequest controller req = let ?req = req in controller
controllerList = [explicitRequest controller1, explicitRequest controller2]
This, however, is rejected by GHC. GHC doesn't seem to infer that explicitRequest hides the implicit parameter required by the controllers.
Am I confused here or is this a bug in GHC?
Thanks in advance, -Stefan
-- [ADV] http://superversion.sf.net [/ADV]