Adding the Roc language to Exercism

I’ve been learning the Roc language recently, it’s a pretty amazing pure functional language inspired from Elm, aiming to be super fast, with great features such as full type inference, tag unions (awesome for many things in particular granular error handling), a separation between apps and platforms, and much more.

I wish the Roc language was supported here on Exercism. I’m happy to help make that happen in any way I can, and some of the main devs of the language also said they’d love to see this happen, so I’m sure I would get some help. What do you think?

1 Like

The practice exercises for each track are built from exercise specifications like hello-world

Once there are volunteers willing to work on a new track, one of the first questions to consider is: what unit testing framework would be used?

Hi keiraville,
Thanks for your guidance :)

what unit testing framework would be used?

We included unit testing into the language to make testing as frictionless as possible.

1 Like

How should the solution and test for the hello-world exercise be expressed in Roc?

For example:

Ruby
solution
test

Haskell
solution
test

Web Assembly
solution
test

Hi @keiraville,

Here’s an example solution:

# HelloWorld.roc
module [hello]

hello = "Hello, World!"

And here’s an example test:

# hello-world-test.roc
app [main] { pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.12.0/Lb8EgiejTUzbggO2HVVuPJFkwvvsfW6LojkLR20kTVE.tar.br" }

import pf.Task exposing [Task]
import HelloWorld exposing [hello]

expect hello == "Hello, World!"

main =
    Task.ok {}

The test can be run using the following command:

roc test hello-world-test.roc

If all the tests pass, the exit code will be 0, and the output will look like this:

0 failed and 1 passed in 542 ms.

If any test fails, the exit code will be non-zero, and the output will look like this:

── EXPECT FAILED in hello-world-test.roc ───────────────────────────────────────

This expectation failed:

6│  expect hello == "Hello, World!"
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


1 failed and 0 passed in 820 ms.

If I correctly understand your suggested file names, and the instructions, we end up with something like

config.json

exercises/practice/hello-world

1 Like

Thanks, that looks good :)
Perhaps for “Run the test suite and make sure that it succeeds.” we should make it “Run the test with roc test hello-world-test.roc and make sure that it succeeds.”?

Lovely! Roc is really great.

@ageron @Anlon-4 what are your GitHub usernames?

2 Likes

Thanks :)
Our github usernames are Anton-4 and ageron

The docs in exercises/practice/.../.docs/instructions.md are exactly the same for every track (programming language). The canonical version is in problem-specifications and for each track we can check that we have the latest version using

bin/fetch-configlet
bin/configlet sync

Instead of editing the instructions, each track can add to the instructions by creating a instructions.append.md file.

I have updated the example repo. Note that the purpose is simply to show how an example exercise would work. The official repos like github.com/exercism/roc and github.com/exercism/roc-test-runner would be created by Erik.

Suppose we would like to implement the phone-number exercise.

Many of the files for the exercise can be created by running something like

bin/create-exercise phone-number

Then we need to port the exercise to Roc source code.

An canonical test case like

    {
      ...
      "property": "clean",
      "input": {
        "phrase": "123456789"
      },
      "expected": {
        "error": "must not be fewer than 10 digits"
      }
    },

might need to be expressed in Roc as

expect clean "123456789" == Err InvalidLength

Converting json to test case source code is an ideal task for automation. How this should be done is one of the next questions to consider.

Where feasible, generators should be written in the track’s own language, but that isn’t required.

C# is using C#
Scala is using Scala
Idris is using Python

Some tracks don’t have a generator.

Instead of editing the instructions, each track can add to the instructions by creating a instructions.append.md file.

Thanks, sounds good!

Converting json to test case source code is an ideal task for automation. How this should be done is one of the next questions to consider.
Where feasible, generators should be written in the track’s own language, but that isn’t required.

We have a json package for Roc so we should be able to make that work :)

I’ve submitted PR #2 on the prototype-roc-track repo, with the minimal files needed to make configlet lint and configlet sync happy. I understand that it’s just a prototype repo, but hopefully this will make it easier to get the final track repo up and running.

Also, I’m happy to help with the generator. Is there a simple one I can draw inspiration from?

1 Like

FYI, I just created this prototype-roc-test-runner repo, mostly copied from the c-test-runner, with some tweaks for Roc. The main difference is the Dockerfile. I’m discussing with the Roc team to see how we can implement the test runner and product the JSON output that Exercism expects.

2 Likes

Here’s a very simple generator that was sufficient for the first exercises it generated, and has only needed minor changes so far:

With each new exercise, we add a short source file with the exercise’s name.

We use Python’s ability to load another source file (module) by name, and call into it from the generator main.

In other languages, I could imagine each exercise providing a trivial main() entry-point that calls into the generator, and passes a callback that generates a test case, given property/input/expected.

I could imagine the callback being optional, and the generator being expected to “do the obvious thing”

1 Like

You may want to consider using the locally cached problem spec data vs requesting the file from GitHub every time. The configlet tool users a local clone and you can piggyback off the same data.

I’ve created the language repo and the test runner repo. You should both have github invites to join the team.

1 Like

If GitHub and Exercism accounts are linked in Integrations then, as PRs are merged into the official repos, Exercism usernames can appear in

https://exercism.org/contributing/contributors?track_slug=roc

https://exercism.org/dashboard

Hi @keiraville,
I added docs, added hello-world and leap, including example code, and I implemented verify-exercises. However, I didn’t receive the invite to join the team (or perhaps it timed out?). Could you please send me another invite, so I can push my changes?
Thanks! :slightly_smiling_face:

The invites would have been from @ErikSchierboom.

Going by emails I received, was there something like

from:	GitHub <noreply@github.com>
subject:	[GitHub] @ErikSchierboom has invited you to join the @exercism organization

...
This invitation will expire in 7 days.