draft: false
---
-In ["Monad Transformers and Effects with Backpack"](https://blog.ocharles.org.uk/posts/2020-12-23-monad-transformers-and-effects-with-backpack.html), [@acid2](https://twitter.com/acid2) presented how to apply Backpack to monad transformers. There is a less-popular approach to deal with effects — [Handle](https://jaspervdj.be/posts/2018-03-08-handle-pattern.html) ([Service](https://www.schoolofhaskell.com/user/meiersi/the-service-pattern)) pattern. I recommend reading both posts at first since they answer many questions regarding the design decisions behind the Handle pattern (why `IO`, why not type classes, etc). In this post, I want to show different implementations of the Handle pattern and compare them. All examples described below are available [in this repository](https://github.com/ak3n/handle-examples).
+In ["Monad Transformers and Effects with Backpack"](https://blog.ocharles.org.uk/posts/2020-12-23-monad-transformers-and-effects-with-backpack.html), [@acid2](https://twitter.com/acid2) presented how to apply Backpack to monad transformers. There is a less-popular approach to deal with effects — [Handle](https://jaspervdj.be/posts/2018-03-08-handle-pattern.html) ([Service](https://www.schoolofhaskell.com/user/meiersi/the-service-pattern)) pattern. I recommend reading both posts at first since they answer many questions regarding the design decisions behind the Handle pattern (why `IO`, why not type classes, etc). In this post, I want to show different implementations of the Handle pattern and compare them. All examples described below are available [in this repository](https://sr.ht/~ak3n/handle-examples/).
-### When you might need the Handle pattern [[simple](https://github.com/ak3n/handle-examples/tree/main/simple)]
+### When you might need the Handle pattern [[simple](https://git.sr.ht/~ak3n/handle-examples/tree/main/item/simple)]
Suppose we have a domain logic with a side effect:
All solutions have their pros and cons and the final choice depends on many factors — especially on the number of side effects and how they interact with each other. We are interested in how to achieve the second one with the Handle pattern.
-### Simple Handle [[simple-handle](https://github.com/ak3n/handle-examples/tree/main/simple-handle)]
+### Simple Handle [[simple-handle](https://git.sr.ht/~ak3n/handle-examples/tree/main/item/simple-handle)]
Let's start with a simple Handle that doesn't support multiple implementations.
Here is the updated domain logic:
We have wrapped our service with the Handle interface. It's not possible to have multiple implementations yet, but we got an interface of the service and can hide all the dependencies of the service into Handle.
-### Handle with records [[records-handle](https://github.com/ak3n/handle-examples/tree/main/records-handle)]
+### Handle with records [[records-handle](https://git.sr.ht/~ak3n/handle-examples/tree/main/item/records-handle)]
The approach with records is described in the aforementioned posts. Records are used as a dictionary with functions just like dictionary passing with type classes but explicitly. `WeatherReporter` module stays the same — it continues to use `WeatherProvider.Handle` while the `WeatherProvider` becomes an interface:
The STG looks as expected. There are two allocations: one in `getCurrentWeatherReportInLondon1` and the other one in `$wcreateWeatherReport`.
-### Handle with Backpack [[backpack-handle](https://github.com/ak3n/handle-examples/tree/main/backpack-handle)]
+### Handle with Backpack [[backpack-handle](https://git.sr.ht/~ak3n/handle-examples/tree/main/item/backpack-handle)]
`WeatherProvider` becomes a signature in the cabal file:
We can see that GHC inlined our constant implementation in the `getCurrentWeatherReportInLondon3` — we show `30` immediately.
-### Handles with Backpack [[backpack-handles](https://github.com/ak3n/handle-examples/tree/main/backpack-handles)]
+### Handles with Backpack [[backpack-handles](https://git.sr.ht/~ak3n/handle-examples/tree/main/item/backpack-handles)]
I decided to go further and make `WeatherReporter` a signature as well. Turned out this step required more actions with libraries. Here is `WeatherReporter.hsig`:
build-depends: base, domain-provider
```
-Instead of `domain` we have `domain-provider` and `domain-reporter`. It allows to depend on them individually and instantiate with different implementations. In [the example](https://github.com/ak3n/handle-examples/blob/main/backpack-handles/backpack-handles.cabal#L52), I have instantiated the provider with implementation from `test-impl` using the reporter from `impl-reporter`. This is useful if you want to gradually write tests for different parts of the logic.
+Instead of `domain` we have `domain-provider` and `domain-reporter`. It allows to depend on them individually and instantiate with different implementations. In [the example](https://git.sr.ht/~ak3n/handle-examples/tree/main/item/backpack-handles/backpack-handles.cabal#L52), I have instantiated the provider with implementation from `test-impl` using the reporter from `impl-reporter`. This is useful if you want to gradually write tests for different parts of the logic.
-### Handle with Vinyl [[vinyl-handle](https://github.com/ak3n/handle-examples/tree/main/vinyl-handle)]
+### Handle with Vinyl [[vinyl-handle](https://git.sr.ht/~ak3n/handle-examples/tree/main/item/vinyl-handle)]
Suppose that we want to extend our `WeatherData` and return not only temperature but wind's speed too. We need to add a field to `WeatherData`:
Let's take a look at what happens in languages with the ML modules system. The users of these languages accept the cost of the explicitness. Although, they would be glad to reduce the boilerplate when it's necessary.
-The theoretical works demonstrate that type classes and modules are not that different. ["ML Modules and Haskell Type Classes: A Constructive Comparison"](https://github.com/ak3n/modules-papers/blob/master/pdfs/Wehr_ML_modules_and_Haskell_type_classes.pdf) showed that a subset of Haskell with type classes can be expressed with ML modules and vice versa with some limitations. ["Modular Type Classes"](https://github.com/ak3n/modules-papers/blob/master/pdfs/main-long.pdf) went further in expressing type classes with modules. It starts with modules as the fundamental concept and then recovers type classes as a particular mode of use of modularity.
+The theoretical works demonstrate that type classes and modules are not that different. ["ML Modules and Haskell Type Classes: A Constructive Comparison"](http://www.stefanwehr.de/publications/Wehr_ML_modules_and_Haskell_type_classes.pdf) showed that a subset of Haskell with type classes can be expressed with ML modules and vice versa with some limitations. ["Modular Type Classes"](https://www.cs.cmu.edu/~rwh/papers/mtc/full.pdf) went further in expressing type classes with modules. It starts with modules as the fundamental concept and then recovers type classes as a particular mode of use of modularity.
The example of bringing type classes to the language with modules can be found in ["Modular implicits"](https://arxiv.org/abs/1512.01895) — an extension to the OCaml language for ad-hoc polymorphism inspired by Scala implicits and modular type classes. It's not supported by mainstream OCaml yet because the proper implementation requires a big change in the language. But here is a small example of how it might look for the `Show` type class:
The Handle pattern demonstrates that Haskell's modules and records are alike in some way — they implement the Handle interface provided to the user, both containing functions. Records are dynamic and can be replaced in the runtime while signatures are static and can be specialized during the compilation. What if we could merge them into one entity?
-[1ML](https://github.com/ak3n/modules-papers/blob/master/pdfs/1ml-jfp-draft.pdf) does that — it merges two languages in one: *core* with types and expressions, and *modules*, with signatures, structures and functors. And requires only System Fω. The example for local signatures mentioned above is the code I adapted from 1ML. Here is the original version:
+[1ML](https://people.mpi-sws.org/~rossberg/1ml/) does that — it merges two languages in one: *core* with types and expressions, and *modules*, with signatures, structures and functors. And requires only System Fω. The example for local signatures mentioned above is the code I adapted from 1ML. Here is the original version:
```ocaml
type EQ =