No, I mean module level for implicit params, my other examples are just more local.
P.S. I will definitely accept partial type signatures for module level private functions, if that’s acceptable by the project’s code style.
No, I mean module level for implicit params, my other examples are just more local.
P.S. I will definitely accept partial type signatures for module level private functions, if that’s acceptable by the project’s code style.
OK, so to be clear, I’m specifically interested in examples of things you would use at the same level as you’re suggesting to use implicit params. So, so far we have
Do any other examples come to mind?
I think there’s a lot of potential in implicit Proxy
s to guide inference and otherwise do cool things in eDSLs GitHub - ramirez7/icfp-2023-inference-tricks
Nice trick! I’ve been experimenting with something similar recently. But that’s not how the ImplicitParams
extension is meant to be used. The GHC manual doesn’t talk about this nor I’ve seen it suggested anywhere. In fact until yesterday I thought I was the only one who used this technique.
I think I was misunderstood here. I’m not saying that local constraints are not possible in GHC. I’m saying that type classes have been originally designed with global resolution in mind.
Implicit parameters and WithDict
introduce different mechanisms but they still look like afterthoughts to me. The implementation of IP
relies on ad-hoc checks (see isIPLikePred
), the semantics of WithDict
are unclear and undocumented.
ghci> class GivenInt where giveInt :: Int
ghci> instance GivenInt where giveInt = 42
ghci> withDict @GivenInt 1 giveInt
1
ghci> withDict @GivenInt 1 $ withDict @GivenInt 2 giveInt
1
ghci> withDict @(IP "int" Int) 1 $ ip @"int"
1
ghci> withDict @(IP "int" Int) 1 $ withDict @(IP "int" Int) 2 $ ip @"int"
2
In these examples withDict
overrides the global GivenInt
instance, but the nested withDict
call doesn’t override the outer one.
However when applying withDict
to IP
the innermost instance wins.
This can only be discovered by trial and error. It isn’t documented anywhere, not even in the GHC code base as far as I know (correct me if I’m wrong).
Ideally I would like to see:
WithDict
) and implicit parameters. I don’t know, maybe a kind-level distinction à la TYPE :: RuntimeRep -> Type
.Until then, I agree with you that implicit parameters are not a good idea in a user-facing API. They should only be use internally and only if you know their limitations and quirks.
Edit:
Upon reflection, WithDict
's behavior in my example is a bug. The fact that it’s allowed to override a statically-defined instance breaks global coherence. I’ll open a ticket on the GHC bug tracker.