Making implicit parameters explicit
Stefan Reich
doc at drjava.de
Thu Nov 6 21:38:26 EST 2003
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]
More information about the Glasgow-haskell-users
mailing list