# Records of Functions and Implicit Parameters

**URL:** <https://discourse.haskell.org/t/records-of-functions-and-implicit-parameters/747>\
**Category:** Show and Tell\
**Created:** [June 18, 2019, 7:23pm UTC](https://discourse.haskell.org/t/records-of-functions-and-implicit-parameters/747 "2019-06-18T19:23:52Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![fommil](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/fommil/32/34_2.png) [@fommil](https://discourse.haskell.org/u/fommil)\
**Post date:** [June 18, 2019, 7:23pm UTC](https://discourse.haskell.org/t/records-of-functions-and-implicit-parameters/747/1 "2019-06-18T19:23:53Z")

</div>

In this article we discuss how it is possible to use `data` and `ImplicitParams` to wire an application.

This is part of a series on alternatives to MTL for application design:

1. [Local Capabilities with MTL](http://discourse.haskell.org/t/local-capabilities-with-mtl/231)
2. [Some limits of MTL with records of functions](http://discourse.haskell.org/t/some-limits-of-mtl-with-records-of-functions/576)
3. [Records of Functions and Implicit Parameters](http://discourse.haskell.org/t/records-of-functions-and-implicit-parameters/747) (this article)

## Records of Functions

In previous articles we have discussed records of functions as an alternative to typeclasses for creating boundaries between components in an application. The main benefit is when a component may have multiple implementations, avoiding the need for orphan instances and lawless typeclasses.

For example, we can define records of functions `Http` and `Database` to describe our interactions with external services:

```haskell
data Http m = Http
  { getUsers :: m [String]
  , postUser :: String -> m ()
  }

data Database m = Database
  { dbHistory :: m [String]
  , dbAdd :: String -> m ()
  }

```

We can write business logic using these records

```haskell
doStuff :: Monad m => Http m -> Database m -> m ()
doStuff http db = do
  users <- (http & getUsers)
  void $ traverse (db & dbAdd) users

```

But the equivalent MTL is much cleaner:

```haskell
doStuff_mtl :: (Monad m, Http m, Database m) => m ()
doStuff_mtl = do
  users <- getUsers
  void $ traverse dbAdd users

```

with no need to explicitly name or pass the `http` and `db`.

## `ImplicitParams`

Growing lists of explicit parameters are even worse in larger codebases with many, deeply nested, record dependencies. One can lose sight of the business logic and be preoccupied passing records to all the functions that need them. What should be a one line change to add a new dependency (e.g. a `Logger`) inevitably results in large diffs that have a high likelihood of conflicting with other work-in-flight.

Encodings have been proposed along the lines of [Classy Lenses](https://hackage.haskell.org/package/lens-4.17.1/docs/Control-Lens-Combinators.html#v:makeClassy) and [`registry`](https://github.com/etorreborre/registry/blob/master/doc/boilerplate.md) to reduce the boilerplate, but they require knowledge of `TemplateHaskell`, lenses and generic programming. The compiler errors can be very confusing.

Here we consider an alternative way to reduce the boilerplate using a language extension designed to introduce dynamic scope: [`ImplicitParams`](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#implicit-parameters).

A function can have an implicit parameter by declaring a named constraint in the type signature. Names must begin with `?`.

Implicit parameters can be used like any other explicit parameter, but remember that the `?` is part of the name.

For example we can convert `doStuff` to use implicit parameters

```haskell
doStuff_ip' :: Monad m => (?http :: Http m, ?db :: Database m) => m ()
doStuff_ip' = do
  users <- (?http & getUsers)
  void $ traverse (?db & dbAdd) users

```

The callers of `doStuff` do not need to pass `Http` or `Database` explicitly, the compiler will inject a value that is locally bound with the same name and type.

We can go further and push the implicit parameters to the functions on the record, e.g. redefine the records

```haskell
data Http m = Http
  { _getUsers :: m [String]
  , _postUser :: String -> m ()
  }

data Database m = Database
  { _dbHistory :: m [String]
  , _dbAdd :: String -> m ()
  }

```

with forwarders

```haskell
getUsers = _getUsers ?http
postUser = _postUser ?http

dbHistory = _dbHistory ?db
dbAdd = _dbAdd ?db

```

Allowing us to write code with records of functions that looks almost identical to the MTL

```haskell
doStuff_ip :: Monad m => (?http :: Http m, ?db :: Database m) => m ()
doStuff_ip = do
  users <- getUsers
  void $ traverse dbAdd users

```

And, of great importance is what the errors look like. What if we forgot to put an implicit `db` in the type signature? This is the error:

```haskell
    • Could not deduce: ?db::Database m arising from a use of ‘dbAdd'’
      from the context: (Monad m, ?http::Http m)
        bound by the type signature for:
                   doStuff_ip :: forall (m :: * -> *).
                                 (Monad m, ?http::Http m) =>
                                 m ()

```

i.e. it says exactly what is missing, and where.

`ImplicitParams` are effectively a way to have opt-in local coherence without the drawbacks of orphan instances. Typeclasses can be reserved for lawful classes exhibiting global coherence, and lawless or non-unique polymorphism can be achieved with `data` and `ImplicitParams`.

> For anybody coming from Scala: `ImplicitParams` are like the `implicit` keyword when in parameter position, but without the implicit search space (i.e. not in `def` or `val` position).

We can turn an explicit value into an implicit one by naming it in a `let` or `where` clause

```haskell
callStuff = do
  http <- mkUsers HttpConfig
  db <- mkDatabase DatabaseConfig
  let ?http = http
      ?db = db
  doStuff_ip

```

Unfortunately, it is not possible to assign an implicit parameter in a `do` binding or a pattern match, it would be great to be able to write

```haskell
callStuff = do
  ?http <- mkUsers HttpConfig
  ?db <- mkDatabase DatabaseConfig
  doStuff_ip

```

perhaps this could be a future `ghc` feature?

Finally, this article would not be complete without discussing the rough edges. In the reddit threads [What’s wrong with ImplicitParams?](https://www.reddit.com/r/haskell/comments/6gz4w5/whats_wrong_with_implicitparams/) and [What about the ImplicitParams Haskell Language Extension?](https://old.reddit.com/r/haskell/comments/kbzjk/what_about_the_implicitparams_haskell_language/) some authors point out that multiple implicit parameters can be introduced with the same name and the compiler accepts it, and other such oddities. Although this extension is almost 20 years old and has proven itself to be production ready (e.g. it is used to implement [`HasCallStack`](https://hackage.haskell.org/package/base-4.12.0.0/docs/GHC-Stack.html#t:HasCallStack)) its reach seems to be limited. I believe it is a little gem and deserves more attention!

Thanks for reading. Please share your experience with `ImplicitParams` (positive or negative) in the comments below, and happy hacking!

---

<div class="post-metadata">

**Author:** ![ekmett](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/ekmett/32/517_2.png) [@ekmett](https://discourse.haskell.org/u/ekmett)\
**Post date:** [June 19, 2019, 11:18am UTC](https://discourse.haskell.org/t/records-of-functions-and-implicit-parameters/747/2 "2019-06-19T11:18:40Z")

</div>

I’m using something similar in my current graphics code, though I’m limiting myself to situations where I’m not using the equivalent of local on the implicit parameters and to when I don’t need a type parameter at present. When combined with the “ReaderT design pattern” you can get ridiculous types that remain quite easy to use. e.g.

> <https://github.com/ekmett/codex/blob/916952cfa87dd2a335e5f571d5812534407e1791/engine/src/Engine.hs#L48>

is horrifying looking, but

> <https://github.com/ekmett/codex/blob/916952cfa87dd2a335e5f571d5812534407e1791/engine/example.hs>

is all the user does to use it.

---

<div class="post-metadata">

**Author:** ![Drezil](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/drezil/32/4989_2.png) [@Drezil](https://discourse.haskell.org/u/Drezil)\
**Post date:** [June 19, 2019, 11:34am UTC](https://discourse.haskell.org/t/records-of-functions-and-implicit-parameters/747/3 "2019-06-19T11:34:21Z")

</div>

I haven’t seen the use of ImplicitParams before and was wondering what they were…

But after reading up they look pretty cool for that use-case. Thanks for showing!

---

<div class="post-metadata">

**Author:** ![palik](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/palik/32/32_2.png) [@palik](https://discourse.haskell.org/u/palik)\
**Post date:** [June 20, 2019, 8:53am UTC](https://discourse.haskell.org/t/records-of-functions-and-implicit-parameters/747/4 "2019-06-20T08:53:20Z")

</div>

[13.20.3. Implicit parameters and polymorphic recursion](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#implicit-parameters-and-polymorphic-recursion) shows an oddity.

---

<div class="post-metadata">

**Author:** ![soareschen](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/soareschen/32/404_2.png) [@soareschen](https://discourse.haskell.org/u/soareschen)\
**Post date:** [June 23, 2019, 7:11pm UTC](https://discourse.haskell.org/t/records-of-functions-and-implicit-parameters/747/5 "2019-06-23T19:11:51Z")

</div>

I am working on a library called implicit-effects [1] that uses the same pattern as you described at the base. My library goes a bit further and make use of type families and constraint kinds to shield the implicit parameters from the users.

I am near in completing implicit-effects for first release, and it is currently a bit lacking on documentation. Hopefully I can share more about the techniques used in the near future.

[1] [https://github.com/maybevoid/implicit-effects](https://github.com/maybevoid/implicit-effects)
