# Recommendations on how to create Koans to learn a library

**URL:** <https://discourse.haskell.org/t/recommendations-on-how-to-create-koans-to-learn-a-library/8116>\
**Category:** Learn\
**Created:** [November 15, 2023, 1:03pm UTC](https://discourse.haskell.org/t/recommendations-on-how-to-create-koans-to-learn-a-library/8116 "2023-11-15T13:03:55Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![turion](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/turion/32/989_2.png) [@turion](https://discourse.haskell.org/u/turion)\
**Post date:** [November 15, 2023, 1:03pm UTC](https://discourse.haskell.org/t/recommendations-on-how-to-create-koans-to-learn-a-library/8116/1 "2023-11-15T13:03:55Z")

</div>

I want to improve the range of documentation I have for my some of my libraries. One kind of documentation I’m looking into is “Koans”. As I understand it, these consist of many small consecutive problems where the learner is required to fix a piece of broken code. Koans exist for different programming languages, and also for some frameworks. I can imagine they make for a fun way to learn a language or library ecosystem.

Therefore I’m looking into creating koans for some of my libraries. I have these requirements:

- The koans should have at least a way of ordering them linearly (ideally even hierarchically, to sort by topics)
- A failing koan should point the learner at a specific file to inspect, with a realistic error message they might encounter in real world
- Type errors and typed holes should be possible in a koan
- Test failures should be possible in a koan (It is fine that these would point to the failing test case instead of at the file where the error to fix is)
- There should be a way to run the koans, which only shows the error message of the smallest/first failing koan, and not all of them at the same time. (`-freverse-errors` goes some way, but not all the way)
- Stretch goal: There should be a way to run a specific koan (ignoring all smaller ones)
- It should be possible to provide the solutions to all the koans, and they should be checked on CI. (It should be checked that the solutions actually compile and test fine.)

Is there anything that achieves this? Tooling, a template, or even an example koan structure that I could mimick? Does anyone have ideas how to do this?

I had some vague ideas what one could do, where I’d be interested about your feedback:

- Create a cabal package (or executable) for every koan, consecutively numbered
- Create a `cabal.project` including all the koans

To run the koans, either:

- `cabal test all` with `-freverse-errors`, and tell people to solve the last error first
- `cabal test 23-foo-koan`, and make sure that the package `n+1-foo-koan` depends on `n-bar-koan`. Possibly, this dependency can be placed under a cabal flag so that one can work on `n+1-foo-koan` without having to solve `n-bar-koan` first.

To ensure that there are solutions and they work, I thought about maybe using a separate branch, and then testing that on CI. But how do I make sure that I only need to make a particular small change to get to that solution? I know, that’s kind of a fuzzy constraint.

---

<div class="post-metadata">

**Author:** ![turion](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/turion/32/989_2.png) [@turion](https://discourse.haskell.org/u/turion)\
**Post date:** [November 15, 2023, 3:13pm UTC](https://discourse.haskell.org/t/recommendations-on-how-to-create-koans-to-learn-a-library/8116/2 "2023-11-15T15:13:12Z")

</div>

Some findings so far:

- Test suites can’t depend on other test suites it seems, so my second idea with dependencies between the koans is a bit harder to realise, I need an internal library _and_ a test suite for every koan
- One might be able to automate this koan idea nicely by writing a custom `Setup.hs`, but this seems a daunting task to me
- If the test suite succeeds it captures all IO, it seems. So I can’t display an encouraging “well done” message, or the result of the program when the learner has solved the koan. Maybe I should just use executables instead.

---

<div class="post-metadata">

**Author:** ![turion](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/turion/32/989_2.png) [@turion](https://discourse.haskell.org/u/turion)\
**Post date:** [January 9, 2024, 10:49am UTC](https://discourse.haskell.org/t/recommendations-on-how-to-create-koans-to-learn-a-library/8116/3 "2024-01-09T10:49:32Z")

</div>

If you want to have a look how it’s going: [GitHub - turion/rhine-koans: Koans to learn rhine](https://github.com/turion/rhine-koans)

Currently, I’m a bit unsure how I should go about with putting the problems (which don’t compile or don’t test) and the solutions (which compile and test) in the same repo. My current setup is having a main branch which contains the problems (so when checking out, one is immediately presented with the problems without seeing the solutions), and a `solution` branch where every Koan is solved. This poses a few challenges:

- I have to lint both branches
- I have to check out the solution branch on CI and test it
  - But a push to `solution` doesn’t trigger the ci, so I need to push it first, or rerun CI

- I have to make sure (currently with a CI check) that `main` is always merged into `solution`, and that the diff between the branches is only in the koans, not anywhere else (i.e. solving the koan is possible by only touching the koan’s code, not its test or so)
- I must not accidentally merge the solution into the main branch

I’m considering not separating solutions and problems via git branches, but instead with a cabal flag. Basically, the flag would just change `main-is` from the koan file to some `Solution.hs`.
