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