https://github.com/Hasnep/roc-ascii
Most of the time it's best to support UTF-8, but sometimes you have data that is just ASCII and you can avoid some of the complexity of UTF-8, so I made a quick package with two types: an ASCII string and an ASCII character. See the docs for more info: https://hasnep.github.io/roc-ascii
I've just released v0.3.0 of roc-ascii which supports Roc v0.0.0-alpha2 and changes the Ascii type from an opaque type to a plain List Char :)
I've just released v0.4.0 v0.4.1 of roc-ascii which supports the new Roc compiler :)
Awesome @Hannes ! I'll add it to the list of libraries available in the Exercism Roc track, since most exercises that manipulate text assume it's ASCII-only. However, it looks like there's currently no release file (.tar.zst)?
Just having some technical difficulties with CI, will be ready soon!
Okay, v0.4.1 has been released!
@Hannes it looks like something's wrong with the release file, for some reason:
── ✗ package download failed ───────────────────────────────────────────────────────────────────────────────────────────
Failed to download and extract this package:
https://github.com/Hasnep/roc-ascii/releases/download/v0.4.1/AnawhDawcVySaW3ywcvfUPuhbXfJK7jcwEHaMBAfVv2y.tar.zst
Error: FileNotFound.
── 1 error and 0 warnings ──────────────────────────────────────────────────────────────── bin/download-dependencies.roc
Uhoh, I didn't test it :sweat_smile: let me have a look!
Oh it looks like the roc bundle command was launched from the root directory instead of inside the src directory:
% tar xvf AnawhDawcVySaW3ywcvfUPuhbXfJK7jcwEHaMBAfVv2y.tar.zst
x src/main.roc
x src/Char.roc
x src/Utils.roc
x src/Ascii.roc
Created an issue for this: https://github.com/roc-lang/roc/issues/10845
I think this is by design, you need to explicitly pass the files you want bundled. It doesn't auto find them like the old compiler
The design for packages and the targets is a little different. The goal is to give platform/package authors more flexibility and control.
FYI, I just ran roc bundle main.roc inside the src directory, and the bundle contains all *.roc files in this directory (presumably because they're listed in main.roc).
Cool, I probably have outdated memory then
I do think we should auto-discover dependencies and include those
like if you include a .roc file which imports other files, we should bring all those in so your bundle isn't broken :sweat_smile:
Just released v0.5.0 which is compatible with the latest Roc nightly and has a functioning release URL you can use. Thanks to @Aurélien Geron for your help!
Here's a small example program:
app [main!] {
cli: platform "https://github.com/roc-lang/basic-cli/releases/download/0.21.0/4rAQg8kUYZ3Vksr4qMQHpaFYNiHSn9GgS7gVxghd1XYV.tar.zst",
ascii: "https://github.com/Hasnep/roc-ascii/releases/download/v0.5.0/5WxqRf15XVko4HxVq5dW8r84s95CxrtvzrjZYwbg9Z3H.tar.zst",
}
import cli.Stdout
import cli.Stderr
import cli.Stdin
import ascii.Ascii
repeat_input_but_shouting! = || {
stdin = Stdin.read_to_end!().map_err(|_| "Failed to read from stdin!")?
msg = Ascii.from_ascii_bytes(stdin).map_err(|_| "Non-ASCII input data!")?
Stdout.write!(msg.to_uppercase().to_str()).map_err(|_| "Failed to write to stdout!")
}
main! = |_| {
match repeat_input_but_shouting!() {
Ok(_) => Ok({})
Err(err_msg) => {
_ = Stderr.line!(err_msg)
Err(Exit(1))
}
}
}
❱ echo hi | roc example.roc
HI
See also https://github.com/showell/roc-webbox/blob/a182bf2/chat/Ascii.roc
Before I realized/remembered that https://github.com/Hasnep/roc-ascii was a thing, I had Claude writing some code, and the same needs came up: is_digit, is_hex_digit, is_alphanumeric, is_whitespace, is_punctuation, is_control, is_letter, to_lowercase, to_uppercase are all in my codebase.
We actually differ on is_whitespace. My version is C's six bytes, which Zig and Go share.
I think there's an argument to upstream some of these to the Roc standard library. OTOH there's a clear argument that individual developers can knock these out pretty easily. So I'm just giving a data point here.
There's also a lot of discussion on #ideas > Add an Ascii type to the standard library about ASCII. It's not totally clear to me whether there were any decisions made there.
I'm now using my ascii library in two different places, which makes me lean more toward wanting them as builtins eventually. It's not a true blocker for me, to be clear. But I'm from the Python school that "batteries included" is a good philosophy, and ascii helpers feel like batteries.
I'm inclined to agree although I think we probably won't add this before 0.1
yeah I want to revisit after 0.1 - I don't really want to add design work projects to 0.1.0's scope unless they're really small and/or urgent :smile:
FWIW there's much design work to do to move https://github.com/showell/roc-webbox/blob/a182bf2/chat/Ascii.roc into builtins soon after 0.1.0.
It's 227 lines of code, mostly tests. The tests are completely exhaustive. The APIs were all cross-checked against Zig, Rust, C, and Go to try to conform to de facto standards. Every single function is implemented with a one-liner.
I had Claude look into calling directly into zig, but the Roc versions pretty much produce the same code as zig. The zig standard library doesn't do anything exotic like lookup tables that we would want to investigate.
Here's a quick taste:
## `a`-`z` to `A`-`Z`; every other byte, 128 to 255 included, unchanged.
## Zig `toUpper`, Rust `to_ascii_uppercase`, C `toupper`, and the per-byte
## rule of `Str.with_ascii_uppercased`.
to_uppercase : U8 -> U8
to_uppercase = |c| if c >= 'a' and c <= 'z' c.bitwise_xor(0x20) else c
Last updated: Nov 04 2026 at 18:54 UTC