{"id":15707233,"url":"https://github.com/robrix/effects-sequences","last_synced_at":"2025-05-12T19:40:51.443Z","repository":{"id":66711101,"uuid":"133193606","full_name":"robrix/effects-sequences","owner":"robrix","description":"Extensible effects à la Oleg, but with fancier effect sets.","archived":false,"fork":false,"pushed_at":"2018-06-05T13:25:10.000Z","size":182,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-01T02:48:16.462Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/robrix.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-05-13T00:29:45.000Z","updated_at":"2021-08-21T16:48:12.000Z","dependencies_parsed_at":"2023-02-27T18:45:52.590Z","dependency_job_id":null,"html_url":"https://github.com/robrix/effects-sequences","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robrix%2Feffects-sequences","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robrix%2Feffects-sequences/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robrix%2Feffects-sequences/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/robrix%2Feffects-sequences/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/robrix","download_url":"https://codeload.github.com/robrix/effects-sequences/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253809192,"owners_count":21967674,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-03T20:38:29.555Z","updated_at":"2025-05-12T19:40:51.388Z","avatar_url":"https://github.com/robrix.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# effects-sequences\n\nAn experiment in [extensible effects à la Oleg](http://okmij.org/ftp/Haskell/extensible/), but using richer sequences for the effect context.\n\n\n## Ideas\n\n### Effect sequences structured as binary trees\n\nRepresent the effect sequence with a (type-level) binary tree instead of a (type-level) list. This lets us talk about the effects in isolation more easily by considering an effect within its leaf node; it also turns out to make membership constraints into a special case of a more general subsequence relation.\n\nIt’s my hope that this shape will also make it easier for us to eliminate effects somewhere in the middle of the sequence instead of always eliminating them at the head of the list.\n\n\n### Handling (sub)sequences of effects\n\nList-based effect sequences result in effect handlers generally having the form:\n\n```haskell\nhandler :: Effect (effect ': effects) a -\u003e Effect effects b\n```\n\nThat is, they remove `effect` from the sequence by interpreting it into a value of type `b`, possibly making requests of other members of `effects`. There are variations on this—@lexi-lambda’s superb [`freer-simple`][] defines a suite of `reinterpret` handlers which additionally _add_ effects to the sequence—but they generally limit the programmer to handling effects at the head of the list. Because handlers delimit the scope of an effect, i.e. you introduce the capability to perform an effect by introducing its handler, you are equally limited to handling effects in LIFO order—you can’t insert effects into the middle of the sequence.\n\nBy virtue of the binary tree structure of the effect sequence, effect handlers in `effects-sequences` have the general form:\n\n```haskell\nhandler :: Effect effects a -\u003e b\n```\n\nThis is often seen in the primitive case:\n\n```haskell\nhandler :: Effect ('S effect) a -\u003e b\n```\n\nand the degenerate case:\n\n```haskell\nrun :: Effect 'Z a -\u003e a\n```\n\nwhich respectively say that when we have a singleton sequence containing `effect`, we can interpret it to produce a `b`, and that when we have handled all of the effects in some (sub)sequence, we can extract a result value.\n\nHowever, this scales up to larger sequences as well. For example, we could implement a `State` effect with the composition of a `Reader` effect and a `Writer` effect, and the handler for such might look like so:\n\n```haskell\nrunStateRW :: state -\u003e Effect ('S (Reader state) ':+: 'S (Writer state)) result -\u003e (result, state)\n```\n\nwhich says that (given some initial value), we can interpret the subsequence composed of `Reader` and `Writer` effects for `state` into a pair of result and final state.\n\n\n[`freer-simple`]: https://github.com/lexi-lambda/freer-simple#readme\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobrix%2Feffects-sequences","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frobrix%2Feffects-sequences","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frobrix%2Feffects-sequences/lists"}