What is the idiomatic way to use effects from a platform in other modules? I have a module which is called Api where I would like to use the Http effects from the platform. However that effect in only imported in app module. Is the plan that all effects should be passed as arguments if they are to be used in modules?
And lets say I have a function called my_send! in the module Api. If this module is to take the cli.Http.send! function as argument I would have to be able to have this signature in my Api module, Request => Result Response _ but the types Request and Response will not be available either. I am a bit lost here. Looks like all modules should be pure and only the app module should do effects but that is very limiting.
Is the plan that all effects should be passed as arguments if they are to be used in modules?
Yes, currently. We originally planned to implement "module params" to make this easier but this is no longer in the plans for the new compiler, we now plan to "pass around small stateful values that can have lots of functions on them without needing to carry around a ton of closures at runtime, and still be used concisely", I presume with help from static dispatch (not implemented yet) :thinking:
@Anton But how do you solve the type issue, the modules would still have to have access to Request, Response types. If I for example have an Api struct that would be defined in the Api module and on the Api struct I have a key called send!, then I would have to use the type signature Request => Response but I will not have access to the types?
We originally planned to implement "module params"
I forgot we did implement module params, this is probably a helpful example.
But how do you solve the type issue
let me think about that...
@Ian McLerran (in roc-ai) re-created his own identical type, it contains all the same fields as InternalHttp.Response. I think there may not be a more convenient solution for now.
@Agus Zubiaga may know more
For Request and Response that works but for example in Tcp.connect! which has a Stream type that is an Opaque type. So the connect function would still cause issues then.
We may also be using structural equality for opaque types, so it could work but yeah, I'm not sure
Let me check
No, it doesn't work
In the original module params proposal it looks like the opaque types could be imported:
this means all Roc modules become architecturally platform-agnostic by default; the only way to couple them to a specific platform would be by using an effect or opaque type which only that platform offers.
I just realized that the same problem is for all external dependencies. For example if I depend on roc-json and I want to use Json.utf8 in some other module I need to send that as a parameter. This will be interesting to see how this will evolve since having to send even pure dependencies as parameters on objects (since I have heard that module parameters will be removed) feels messy already in my small code example.
Yeah, looks like you can just import that :sweat_smile:
https://github.com/imclerran/roc-ai/blob/3d4e7f1a4a41799bbbb12561ecc2074508200b11/package/Chat.roc#L18
Forgot to think of the obvious solution :p
Interesting, I am getting an error when trying that but I think it has to do with my project layout.
Do you know how I can use a local platform for my project, currently I am just using the examples folder in basic-cli platform but that is not so nice, I would like to have a local build of basic-cli and import that in my roc project. However when I try to import from my external project the same way as is done in examples pf: platform "<path-to-basic-cli>/platform/main.roc"
this just fails.
I think you need to do the following in your local basic cli folder dirst:
./jump-start.sh
roc build.roc --linker=legacy
Can you share the error?
Anton said:
Forgot to think of the obvious solution :p
Your original question immediately made me think of module params
Now I got the platform import working, not sure what was wrong before.
Haha yes, it was a very nice discussion, I guess the module params and the sending effects as params are nice patterns for testing your code. But now I am able to import both platform effects and other third part dependency into any module in my project with just
import cli.Stdout or json.Json
Last updated: Jul 06 2025 at 12:14 UTC