Question on simulation, couldn't the roc effect interpreter just track a state?
It could do this, I guess the main cost there is that then you must create an ad hoc state for each interpreter and simulation you want to run
another alternative is to provide effect handlers instead of an effect interpreter, and each effect handler takes the same “state” parameter. but then the language needs some machinery to make sure the state parameter is consistent - Im not sure if this idea works.
A message was moved here from #ideas > Stored ability by Richard Feldman.
I'm interested in both of these ideas! What would they look like? :thinking:
like let's say Task is a builtin, and the way you specify what entries get put into the state machine the same way effects get specified today (you provide a type signature and the compiler takes care of generating it)
let's also assume we can have a language feature for creating simulated tasks (e.g. by specifying an effect interpreter)
what would those language features look like? how would they interact with map2? etc.
Ill follow up here tomorrow
let's also assume we can have a language feature for creating simulated tasks (e.g. by specifying an effect interpreter)
I will note right now that these are two different things though, right. Creating a task to simulate by way of an effect interpreter is separate from defining an effect interpreter. thy are two halves of the whole!
yeah definitely
like in the #ideas > Task as builtin proposal, in Roc code you specify types for the task operations you want to exist, and then the compiler generates a state machine from that, and then the host interprets that state machine
so potentially, there could be a way to specify that state machine interpreter in pure Roc code instead
the basic premise of the handler idea is you provide only the handlers you need and the language plugs everything in for you for the purposes of effect interpretation. I'm eliding some details that are important here, but suppose you have effects of the form
httpGet : Request -> Task Response ...
tcpWrite : Bytes -> Task {} ...
tcpRead : Nat -> Task Bytes ...
# so on
suppose you now construct a Task whose evaluation you'd like to simulate (in this model, the simulation is a Task directly, composed inductively of the effects defined above). Let's say we have our effect-to-be-evaluated in a variable programEffect. There are two ways we could imagine evaluating programEffect in Roc code directly:
programEffect. This is doable but a bit cumbersome if we want to parameterize the interpreter for different effects under evaluation, since you'll be writing boilerplate code (things like, "evaluate this and call the next continuation"; think pattern matches like TcpWrite bytes k -> doSomethingWithBytes bytes |> \_ -> k (Ok {})). There are also some edges to make things like map2 work, but that can probably be made to work.evaluate that takes a task and handlers of the form handleHttpGet : state, Request -> (state, Result Response ...) corresponding to httpGet : Request -> Task Response ... (so, given effect e : a1, ..., an -> Task o e, handleE : state, a, ..., an -> (state, Result o e)). The library/compiler then assembles an interpreter for you based on these handlers, and defaults to error handlers for those that aren't specified. For example given the callevaluate programEffect {
handleTcpRead : \state, {} ->
bytes = if state.count == 1 then [1,2, 3] else [1,2,3,4]
({state & count = state.count + 1}, Ok bytes)
}
this would evaluate programEffect in "the natural way", handling tcpRead as provided and crashing on httpGet/tcpWrite effects. It would handle map2 in the only way map2 can be handled.
I'm intentionally glossing over the syntax and whether this would need to be builtin to the language or provided by a library, but I think it requires at least some language support (as any effect interpreter would, namely because of map2). I hope this example elucidates my original message in the thread.
it does, thanks! :thumbs_up:
Last updated: Jun 16 2026 at 16:19 UTC