{"id":20082045,"url":"https://github.com/exercism/sml","last_synced_at":"2026-02-06T03:02:08.098Z","repository":{"id":21220919,"uuid":"24534916","full_name":"exercism/sml","owner":"exercism","description":"Exercism exercises in Standard ML.","archived":false,"fork":false,"pushed_at":"2026-02-01T04:18:18.000Z","size":750,"stargazers_count":28,"open_issues_count":10,"forks_count":37,"subscribers_count":9,"default_branch":"main","last_synced_at":"2026-02-01T15:34:42.578Z","etag":null,"topics":["community-contributions-accepted","exercism-track","maintained"],"latest_commit_sha":null,"homepage":"https://exercism.org/tracks/sml","language":"Standard ML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/exercism.png","metadata":{"funding":{"github":["exercism"],"custom":["https://exercism.org/donate"]},"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2014-09-27T15:15:18.000Z","updated_at":"2026-02-01T04:18:20.000Z","dependencies_parsed_at":"2023-01-11T21:07:37.060Z","dependency_job_id":"cdebb4ae-175a-4924-bbe2-be4ebad41888","html_url":"https://github.com/exercism/sml","commit_stats":{"total_commits":292,"total_committers":35,"mean_commits":8.342857142857143,"dds":0.8013698630136986,"last_synced_commit":"b3e87f4dde2674bb745c67745606f2da3ac4da83"},"previous_names":["exercism/xsml"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/exercism/sml","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exercism%2Fsml","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exercism%2Fsml/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exercism%2Fsml/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exercism%2Fsml/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/exercism","download_url":"https://codeload.github.com/exercism/sml/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/exercism%2Fsml/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29147377,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-06T02:39:25.012Z","status":"ssl_error","status_checked_at":"2026-02-06T02:37:22.784Z","response_time":59,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["community-contributions-accepted","exercism-track","maintained"],"created_at":"2024-11-13T15:41:31.135Z","updated_at":"2026-02-06T03:02:08.075Z","avatar_url":"https://github.com/exercism.png","language":"Standard ML","readme":"# Exercism Standard ML Track\n\n[![configlet](https://github.com/exercism/sml/workflows/Configlet/badge.svg)](https://github.com/exercism/sml/actions/workflows/configlet.yml?query=workflow%3Aconfiglet) [![sml / ci](https://github.com/exercism/sml/workflows/sml%20/%20ci/badge.svg)](https://github.com/exercism/sml/actions/workflows/ci.yml?query=workflow%3A%22sml+%2F+ci%22)\n\nExercism exercises in Standard ML.\n\n## Setup\n\nEven though there are multiple Standard ML implementations, we'll stick to\n[PolyML](https://polyml.org/).\n\nPlease read [INSTALLATION.md](docs/INSTALLATION.md) for more info.\n\n## Contributing Guide\n\nAny type of contribution is more than welcome!\n\nBefore opening a pull request please have look into [Contributors Pull Request\nGuide](https://exercism.org/docs/building/github/contributors-pull-request-guide).\n\n## Contributing a new exercise\n\nUsually an exercise is derived from one of the exercises in the\n[problem-specifications](https://github.com/exercism/problem-specifications) repository. If you want\nto contribute a completely new exercise, consider opening a pull request there to make it available\nto all tracks.\n\nThere is a [comprehensive guide][guide-practice-exercise] on how to add an exercise to one of the\nexercism tracks. It is advisable that you skim over the text. You don't have to remember everything,\nwe recall the essentials here anyway. We also provide the track-specific details here. Down below we\ndescribe tooling which helps you with the boilerplate.\n\nBasically, adding an exercise means to do the following things.\n\n- Register the exercise in `{{ repo-path }}/config.json`,\n- Use tooling to generate *exercise-folder* `exercises/practice/{{ slug }}/`,\n- Provide a solution for the exercise in `example.sml`,\n- Check if the linter (configlet) is satisfied.\n\n### Register exercise in `{{ repo-path }}/config.json`\n\nThis step needs to be done manually. You have to add a block looking like that under\n`exercises/practice`:\n\n```json\n{\n  \"exercises\": {\n    \"practice\": [\n      {\n        \"slug\": \"flatten-array\", // the slug from `problem-specifications`\n        \"name\": \"Flatten Array\",\n        \"uuid\": \"fb0a030d-33bc-4066-a30a-1b8b02cc42f1\", // use `configlet uuid` to generate this\n        \"practices\": [],\n        \"prerequisites\": [],\n        \"difficulty\": 1,\n        \"topics\": []\n      },\n      // more exercises ...\n    ],\n    // more stuff ...\n  },\n  // more stuff ...\n}\n```\n\nTo generate a unique `uuid` just execute the following on the command line:\n\n```shell\n$ bin/fetch-configlet # to fetch the latest version of configlet\n$ bin/configlet uuid  # paste the output into the `uuid` field.\n```\n\n### Generate exercise-folder `exercises/practice/{{ slug }}/`\n\nA folder similar to this one has to be created:\n\n```sh\nexercises/practice/flatten-array/\n├── flatten-array.sml          # stub-file displayed to studend on website\n├── testlib.sml                # copy of the test-library (track-specific)\n├── test.sml                   # actual test-suite\n├── .docs\n│   ├── instructions.append.md # optional track-specific file augmenting `instructions.md`\n│   └── instructions.md        # contains (track-independent) description of the exercise\n└── .meta\n    ├── config.json            # you may add yourself as author here\n    ├── example.sml            # solution proving that the test-suite can actually be satisfied\n    └── tests.toml             # specifies which tests from `problem-specifications` are implemented\n```\n\nThe easiest way to autogenerate the boilerplate is to execute [configlet\nsync](https://exercism.org/docs/building/configlet/sync) in combination with the track specific tool\n`bin/generate`. The former is responsible for required files with \"generic\" content, and the latter\nfor required files with sml-specific content\n\n```shell\n$ bin/configlet sync -yu --tests include --docs --filepaths --metadata -e {{ slug }}\n$ bin/generate {{ slug }}\n```\n\n**Note on `bin/generate`:** You need Python 3.5+. It may fail with some exercises. Reasons:\n`canonical-data.json` does not exist, or type mismatch (in these situation you can use `--force`\noption). In those cases you will have to create the files manually.\n\n**IMPORTANT:** Currently the test-framework expects `example.sml` to be inside `.meta/`, which is\nnot the case right after execution of `bin/generate`. As a workaround you should move the file\nmanually and update the path in `.meta/config.json` accordingly.\n\n### Provide a solution in `example.sml`\n\nThe most creative part is to write a valid solution `example.sml` which passes the test-suite. To\nverify that your solution is valid just execute the tests like so\n\n```shell\n$ make test-{{ slug }}\n```\n\n*Alternatively* you can verify your solution by\n\n```shell\n$ # You might need `sudo` since docker is invoked:\n$ bin/test {{ slug }}\n```\n\nUnder the hood this uses `docker` to run the tests in the `sml-test-runner` image. This is\nessentially what happens if a student submits their own solution.\n\n### Linting\n\nFinally check if the linter is satisfied with your work\n\n```shell\n$ bin/configlet lint\n```\n\n## Exercise Tests\n\nYou can execute tests by\n\n```shell\n$ make test            # all tests\n$ make test-{{ slug }} # single test\n```\n\nMainstream languages usually have one or more popular test-frameworks. Standard ML is not blessed\nwith this convenience. Therefore the track implements its own \"test-framework\" `lib/testlib.sml`. It\ngets the job done. For technical reasons each exercise must provide its own copy of the testlib.\n\nAny updates to `lib/testlib.sml` have to be synced to all exercises by\n\n```\n$ make redeploy-testlib\n```\n\nWe don't want to deal with multiple versions of testlib. Hence the redeploy script is the only way to update the testlib of any exercise.\n\n\n[guide-practice-exercise]: https://exercism.org/docs/building/tracks/practice-exercises\n","funding_links":["https://github.com/sponsors/exercism","https://exercism.org/donate"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexercism%2Fsml","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fexercism%2Fsml","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fexercism%2Fsml/lists"}