]> git.xn--bdkaa.com Git - xn--bdkaa.com.git/commitdiff
Fix links to code
authorEvgenii Akentev <i@ak3n.com>
Wed, 2 Nov 2022 19:23:58 +0000 (23:23 +0400)
committerEvgenii Akentev <i@ak3n.com>
Wed, 2 Nov 2022 19:23:58 +0000 (23:23 +0400)
content/posts/implementations-of-the-handle-pattern.md

index 26f28a7a30a5cf83d8caf07d8d75757db9c5545e..f97ae7fdb057730a3775784a47fcb99e569a94e6 100644 (file)
@@ -5,9 +5,9 @@ draft: false
 tags: [haskell, backpack]
 ---
 
-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/).
+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://git.ak3n.com/?p=handle-examples.git).
 
-### When you might need the Handle pattern [[simple](https://git.sr.ht/~ak3n/handle-examples/tree/main/item/simple)]
+### When you might need the Handle pattern [[simple](https://git.ak3n.com/?p=handle-examples.git;a=tree;f=simple)]
 
 Suppose we have a domain logic with a side effect:
 
@@ -54,7 +54,7 @@ At some point in time, there appeared a need for tests to ensure that the domain
 
 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://git.sr.ht/~ak3n/handle-examples/tree/main/item/simple-handle)]
+### Simple Handle [[simple-handle](https://git.ak3n.com/?p=handle-examples.git;a=tree;f=simple-handle)]
 
 Let's start with a simple Handle that doesn't support multiple implementations.
 Here is the updated domain logic:
@@ -112,7 +112,7 @@ getWeatherData _ _ _ = return $ WeatherData 30
 
 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://git.sr.ht/~ak3n/handle-examples/tree/main/item/records-handle)]
+### Handle with records [[records-handle](https://git.ak3n.com/?p=handle-examples.git;a=tree;f=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:
 
@@ -236,7 +236,7 @@ The result of `getWeatherData "London" "now" = ipv1_s1Cp` is then passed to `cre
 
 The STG looks as expected. There are two allocations: one in `getCurrentWeatherReportInLondon1` and the other one in `$wcreateWeatherReport`.
 
-### Handle with Backpack [[backpack-handle](https://git.sr.ht/~ak3n/handle-examples/tree/main/item/backpack-handle)]
+### Handle with Backpack [[backpack-handle](https://git.ak3n.com/?p=handle-examples.git;a=tree;f=backpack-handle)]
 
 `WeatherProvider` becomes a signature in the cabal file:
 
@@ -400,7 +400,7 @@ Handle = \r [eta_B1] Handle [eta_B1];
 
 We can see that GHC inlined our constant implementation in the `getCurrentWeatherReportInLondon3` — we show `30` immediately.
 
-### Handles with Backpack [[backpack-handles](https://git.sr.ht/~ak3n/handle-examples/tree/main/item/backpack-handles)]
+### Handles with Backpack [[backpack-handles](https://git.ak3n.com/?p=handle-examples.git;a=tree;f=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`:
 
@@ -447,9 +447,9 @@ library impl-reporter
   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://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.
+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.ak3n.com/?p=handle-examples.git;a=blob;f=backpack-handles/backpack-handles.cabal;h=6cfe4f87359e2bf02fff72cfea75d2669818b7e1;hb=HEAD#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://git.sr.ht/~ak3n/handle-examples/tree/main/item/vinyl-handle)]
+### Handle with Vinyl [[vinyl-handle](https://git.ak3n.com/?p=handle-examples.git;a=tree;f=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`: