effect modules is a special concept in Gren that is only available in gren-lang/* packages.
An effect module is essentially an "application" within your application. It has its own state and update routine, and can be communicated with through commands and subscriptions.
The API has always felt like magic to me, and the whole subscription upkeep has always been a pain in the neck to maintain.
That said, with proposal #218 and #371 , we don't actually need them anymore.
Rewriting an effect module to normal Gren code would essentially follow these steps:
- Remove all effect module related machinery, and end up with a normal model-init-update module.
- Include the module's
Msg type as a subset of the platform's Task definition
- Wrap the user's application in a platform specific
Program, created by calling something like Browser.application, that can delegate messages between the user application and the "effect module".
- Subscriptions are essentially just an array of functions that wrap a
Msg coming from the effect module in a user-specific Msg type. Meaning the "effect module" returns a Task/Cmd for sending Msg to the application, but is wrapped by a mapping function before being passed to the application's update function.
In other words, effect modules just follows the nested TEA pattern.
Regarding ports
If we don't need effect modules for defining Cmd and Subs, and if Task is just an extensible tagged union, do ports actually have to be a special construct in the language at all?
No, not really.
We could limit the number of ports to 1, then add variants to Task that let's you listen for messages from the outside world, send messages to the outside world, or both as a task.
If so, we would lose the ability to define multiple ports (which I'm not sure is a good idea to begin with) and we would lose automatic encoding/decoding in the simple cases. On the other hand, it would remove yet another special construct from the language, simplifying the semantics.
effect modules is a special concept in Gren that is only available in
gren-lang/*packages.An effect module is essentially an "application" within your application. It has its own state and update routine, and can be communicated with through commands and subscriptions.
The API has always felt like magic to me, and the whole subscription upkeep has always been a pain in the neck to maintain.
That said, with proposal #218 and #371 , we don't actually need them anymore.
Rewriting an effect module to normal Gren code would essentially follow these steps:
Msgtype as a subset of the platform'sTaskdefinitionProgram, created by calling something likeBrowser.application, that can delegate messages between the user application and the "effect module".Msgcoming from the effect module in a user-specificMsgtype. Meaning the "effect module" returns aTask/Cmdfor sendingMsgto the application, but is wrapped by a mapping function before being passed to the application's update function.In other words, effect modules just follows the nested TEA pattern.
Regarding ports
If we don't need
effect modulesfor definingCmdandSubs, and ifTaskis just an extensible tagged union, do ports actually have to be a special construct in the language at all?No, not really.
We could limit the number of ports to 1, then add variants to
Taskthat let's you listen for messages from the outside world, send messages to the outside world, or both as a task.If so, we would lose the ability to define multiple ports (which I'm not sure is a good idea to begin with) and we would lose automatic encoding/decoding in the simple cases. On the other hand, it would remove yet another special construct from the language, simplifying the semantics.