]> git.xn--bdkaa.com Git - xn--bdkaa.com.git/commitdiff
Fix links
authorEvgenii Akentev <i@ak3n.com>
Thu, 10 Feb 2022 14:26:17 +0000 (19:26 +0500)
committerEvgenii Akentev <i@ak3n.com>
Thu, 10 Feb 2022 14:26:17 +0000 (19:26 +0500)
content/posts/implementations-of-the-handle-pattern.md
content/posts/thoughts-on-backpack-modules-and-records.md

index 0f5b724075961b15fe86122f10e0a5f160668e70..5dd6a7776ede82715bfd7f04a9798618320f7852 100644 (file)
@@ -4,9 +4,9 @@ date: 2021-01-31
 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:
 
@@ -53,7 +53,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://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:
@@ -111,7 +111,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://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:
 
@@ -235,7 +235,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://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:
 
@@ -399,7 +399,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://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`:
 
@@ -446,9 +446,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://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`:
 
index ebfe1df0a68b6b6a02f05b51f99ec09c9f5f8783..22ee0ddbe13377d1d0883ea55dd98ece6049893d 100644 (file)
@@ -127,7 +127,7 @@ We understood that Backpack is a tool that uses the compiler and the package man
 
 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:
 
@@ -242,7 +242,7 @@ This is just an example to demonstrate how it might look like. It introduces a m
 
 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 =