Making implicit parameters explicit

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]

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]

On Wed, Nov 05, 2003 at 09:13:12PM +0100, 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]
You have just been bitten by monomorphism restriction. Write a type signature for controllerList and it should work: controllerList :: (?req :: Request) => [String] Best regards, Tom -- .signature: Too many levels of symbolic links

On Thu, Nov 06, 2003 at 10:02:26PM +0100, Tomasz Zielonka wrote:
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]
You have just been bitten by monomorphism restriction. Write a type signature for controllerList and it should work:
controllerList :: (?req :: Request) => [String]
Maybe in such situation GHC could suggest that the problem can be caused by monomorphism restriction ? Best regards, Tom -- .signature: Too many levels of symbolic links

Well yes, but what I actually want is to instantiate controllerList statically; the implicit parameter should ideally be embedded, like this: controllerList :: [(?req :: Request) => String] I don't think that is a legal Haskell type though... -Stefan Tomasz Zielonka wrote:
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]
You have just been bitten by monomorphism restriction. Write a type signature for controllerList and it should work:
controllerList :: (?req :: Request) => [String]
Best regards, Tom
participants (2)
-
Stefan Reich
-
Tomasz Zielonka