Is it possible to update a single element in a List without copying the entire List? I'm looking through the Roc Tutorial, and I didn't see a List.set
function.
Some context, I am an F# developer currently, and I write discrete event simulations. I often have a State record that has several fields of Num List
that model the current state of the system.
State : { flowRates: Num List, volumes: Num List }
These fields represent things like Flow Rates and Volumes in tanks. As I process events, I have to update individual elements in the Num List
. Flow rates are changing, for example.
I have written these in a pure-functional style, but in F# the performance is terrible due to all the copying that needs to occur. I wonder if the Roc compiler is smart enough to avoid these copies if I write my code correctly. Since there doesn't appear to be a List.set
function, it does not appear that this would be possible, or am I missing something?
I'm excited about Roc but unsure if I could get the performance I need.
Roc has optimizations to update in place when possible.
there is a List.set
, in fact! https://www.roc-lang.org/builtins/List#set
and yeah it does what you want - if the list is unique, it will update in-place
(we do need to fix the formatting on that type in the docs though haha)
Is there a way to see if your lists are unique? I'd turn that compiler warning on for sure :joy:
Not currently. Also, in certain cases, it can only be know at runtime and not compile time.
we've discussed things like this a bunch in the past; the current thinking is that separate performance-oriented tools outside the compiler is most likely the way to go
it's tricky to try to guarantee uniqueness without getting into a more Rust-like user experience where the type system has to incorporate them and you get compiler errors for scenarios that you know wouldn't be a problem in practice
That sounds similar to JetBrains Rider which has an extension that lets you know if you are heap-allocating and making defensive copies which is incredibly helpful.
From my standpoint, Roc is beautiful and concise. Roc would make it easier to get a Discrete Event Simulation (DES) up and running faster using Functional Style than writing something in another language with a Procedural Style.
The problem will be if I end up having to spend significant amounts of time getting the performance I need hunting down non-uniqueness.
I know I can get the perf I need with a Procedural Style, but it will take longer to write a correct DES.
Again, NOT complaining! I used to think it would be impossible to get high-perf FP language but Roc gives me hope.
If you start working on something. People here would definitely be willing to help.
Is there a possibility to create a platform that would enforce linear types (like ATS or Austral)? That way, there would be no question of having a non-unique reference.
Is there a possibility to create a platform that would enforce linear types (like ATS or Austral)?
I still don't understand the Platforms thing, but it would be wonderful to have a system that enforced the uniqueness of references. Probably annoying until you know how to write code in that way but ultimately quite helpful.
No, couldn't be done by a platform.
Also, I think to add on, besides 1 or 2 specific sharp edges I can think of, I believe that for the most part, you can write code in a normal manner and copies should be pretty minimal.
have u guys ever talked about quantitative type theory idris2 style https://arxiv.org/pdf/2104.00480.pdf ?
Idris2 has definitely been talked about and people working on the compiler know about it. I don't have an answer to type detaiil specifics though. I regularly talk about more powerful types for performance but have limited literature experiences. Have much more experience having no type level help and just making things fast with lots of benchmarks, profiling, and such.
i think we really want to avoid using type systems built on dependent type theories if possible. they are powerful, but their algorithmic complexity is very high (slow compile times) and have poor DX right now (though of course QTT is much better in this regard, still not great though). One thing is that, at least I, am not aware of any type system built on a dependent type theory that has complete type inference
For me, it would be enough to have feedback in the IDE that a copy is occurring. I don't necessarily need the compiler to force me to behave in a particular way. That's how the Rider plugin works for warning on defensive copies of structs or heap allocation.
That is definitely a feature i want to make a reality
Though extremely low priority
Without that visibility, I'm afraid I would spend large amounts of time "debugging" the copying of data since there's no way to make a fast simulation without minimizing the memcpy.
Though extremely low priority
That's what I was guessing
Recently, I manage to nicely display memory allocations at the function level. Where it made a flame graph based on the number of bytes allocated over the run of the program (though total count of allocations may be more useful in some cases)
Also, i don't think it is hard to write roc code in a way to avoids allocations due to lack of uniqueness. Just need to learn a few rules/tips.
Ayaz Hafiz said:
i think we really want to avoid using type systems built on dependent type theories if possible. they are powerful, but their algorithmic complexity is very high (slow compile times) and have poor DX right now (though of course QTT is much better in this regard, still not great though). One thing is that, at least I, am not aware of any type system built on a dependent type theory that has complete type inference
not all of it
i agree this stuff tends to be too complex
but specifically something like idris' quantity annotation?
what is the quantity annotation?
https://idris2.readthedocs.io/en/latest/tutorial/multiplicities.html
The 1 multiplicity expresses that a variable must be used exactly once
Doesn't that add the same problem as linear types? anything with a value set to 1
you have to follow through all names and function calls to make sure it isn't duplicated?
I guess if you force labeling all functions, it reduces that chasing some.
Last updated: Jul 06 2025 at 12:14 UTC