# Why not implicit parameters?

**URL:** <https://discourse.haskell.org/t/why-not-implicit-parameters/10247>\
**Category:** Learn\
**Created:** [August 29, 2024, 2:25am UTC](https://discourse.haskell.org/t/why-not-implicit-parameters/10247 "2024-08-29T02:25:40Z")\
**Posts on this page:** 3\
**Page:** 2

<div class="post-metadata">

**Author:** ![tomjaguarpaw](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/tomjaguarpaw/32/1230_2.png) [@tomjaguarpaw](https://discourse.haskell.org/u/tomjaguarpaw)\
**Post date:** [September 5, 2024, 11:41am UTC](https://discourse.haskell.org/t/why-not-implicit-parameters/10247/22 "2024-09-05T11:41:51Z")

</div>

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

- primitives: they exist at module top level but we don’t normally expose them in APIs
- partial type signatures

Do any other examples come to mind?

---

<div class="post-metadata">

**Author:** ![Ambrose](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/ambrose/32/5672_2.png) [@Ambrose](https://discourse.haskell.org/u/Ambrose)\
**Post date:** [September 5, 2024, 4:57pm UTC](https://discourse.haskell.org/t/why-not-implicit-parameters/10247/23 "2024-09-05T16:57:28Z")

</div>

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](https://github.com/ramirez7/icfp-2023-inference-tricks)

---

<div class="post-metadata">

**Author:** ![lortabac](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/lortabac/32/4597_2.png) [@lortabac](https://discourse.haskell.org/u/lortabac)\
**Post date:** [September 5, 2024, 7:43pm UTC](https://discourse.haskell.org/t/why-not-implicit-parameters/10247/24 "2024-09-05T19:43:04Z")

</div>

> [@sand-witch](#):
>
> Not quite true. `?symbol :: T` is indeed just a `Symbol`, but you can use `IP` type class with locally defined dummy data tags

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.

> [@sand-witch](#):
>
> > Implicit parameters are implemented by piggybacking on type classes, which have been designed for static, global resolution.
> 
> Wrong! See the story around `withDict` and co. There is a lot of work aside implicit params that is done in GHC to resolve type classes with the right scoping

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.

```haskell
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:

- Well-defined and documented semantics.
- A clear difference between global constraints, local constraints (meant to be set with `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.

[Previous page](https://discourse.haskell.org/t/why-not-implicit-parameters/10247.md?page=1)
