I am new to Roc, have looked at some closed issues implementing built-in functions, and would like to learn more about how they are implemented from a general point of view.
My first impression is that built-in functions are implemented in Rust by defining Rust representations of Roc expressions - mimicking what the Roc parser would create.
Is that impression accurate?
Are all standard-library functions implemented like this?
Would it be possible to implement built-in / standard-library functions in Roc if (like for Result.isOk) no external functionality is required for the implementation?
I can imagine these questions have already been discussed but did not find anything relevant. Are there relevant discussions in issues you can point me to?
Welcome Sebastian! I've been involved in the project for a few months and I can answer some of this but not all!
Yes as far as I can tell, all of Roc's standard library functions are builtins rather than being written in Roc. I hadn't realised that it was literally all of them until you mentioned it!
Most languages have at least some functions built in to the compiler for efficiency. Sometimes that lets you do things in a more optimised way than you could in the source language. Most of Roc's builtins are implemented using the compiler's internal data structures, as you mentioned. A few of them are implemented in Zig. The Zig functions are here.
As I mentioned, I'm not sure why we have 100% of them as builtins. Intuitively it seems like Roc would work just as well in many cases. Maybe the feeling was that if we need some of them as builtins, might as well just do all of them that way. Someone else will have to fill in the history there.
it's to prevent an elm native/kernel code scenario: if you can change or add roc builtins too easily, you can break the guarantees of the language (purity, mostly) and that would be a worse experience
also it's a minor efficiency gain: fewer files to load or cache
Thanks Brian and Folkert!
I now understand, the standard library is not implemented in Roc intentionally, although I'm not sure I fully understand the reasoning. On a high level, I can see that it would be easy to break purity if it was easy to add built-in functions using Rust. I do not yet see how implementing pure library functions in Roc could break purity.
When I started with Haskell twenty years ago, I learned a lot of the basics from reading the Haskell 98 Prelude. Considering programs not only for computers to run but also for people to communicate ideas, I think a standard library (mostly) implemented in Roc could be a default example for new Rocsters where they could learn about the API of the standard library and how to write idiomatic Roc code.
I'd like to understand better why Roc seems to follow a different path, implementing even pure functions that could be efficiently implemented in Roc using Rust instead. I'm curious to learn more, if anyone can elaborate or link to previous discussions regarding this decision.
Couple of things
List
module is full of common haskell patterns. But our list is an Array (chunk of memory) and so we can't write those nice recursive functions for listswe also annotate a lot of the stdlib functions with extra information that optimization steps use later. Those annotations shouldn't be in userspace because Roc couldn't claim to be memory safe anymore if they were :big_smile:
there are a nonzero number of convenience functions in the stdlib there could be implemented in a plain .roc file purely in terms of other functions that couldn't be implemented that way, but:
so overall the downsides seem to outweigh the upsides.
I see. Thanks for elaborating!
great question! :smiley:
Last updated: Jul 05 2025 at 12:14 UTC