{"id":22258073,"url":"https://github.com/coot/purescript-redox","last_synced_at":"2025-08-11T15:09:39.544Z","repository":{"id":58242342,"uuid":"86641767","full_name":"coot/purescript-redox","owner":"coot","description":"Data store(s) for purescript applications. Use your own DSL to update the global state.","archived":false,"fork":false,"pushed_at":"2018-10-07T12:33:50.000Z","size":106,"stargazers_count":19,"open_issues_count":3,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-11T20:27:41.781Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"PureScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/coot.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-03-30T00:32:13.000Z","updated_at":"2025-06-26T06:35:00.000Z","dependencies_parsed_at":"2022-08-31T04:22:10.968Z","dependency_job_id":null,"html_url":"https://github.com/coot/purescript-redox","commit_stats":null,"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"purl":"pkg:github/coot/purescript-redox","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coot%2Fpurescript-redox","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coot%2Fpurescript-redox/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coot%2Fpurescript-redox/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coot%2Fpurescript-redox/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/coot","download_url":"https://codeload.github.com/coot/purescript-redox/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/coot%2Fpurescript-redox/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269908535,"owners_count":24494574,"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","status":"online","status_checked_at":"2025-08-11T02:00:10.019Z","response_time":75,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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-12-03T08:13:24.287Z","updated_at":"2025-08-11T15:09:39.514Z","avatar_url":"https://github.com/coot.png","language":"PureScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# REDOX - global state management for PureScript apps\n\n[![Maintainer: coot](https://img.shields.io/badge/maintainer-coot-lightgrey.svg)](http://github.com/coot) [![documentation](https://pursuit.purescript.org/packages/purescript-redox/badge)](https://pursuit.purescript.org/packages/purescript-redox)\n[![Build Status](https://travis-ci.org/coot/purescript-redox.svg?branch=master)](https://travis-ci.org/coot/purescript-redox)\n\nRedox - since it mixes well with [Thermite](https://github.com/paf31/purescript-thermite) ;)\n\nThis is `redux` type store, but instead of forcing you to write interpreter\nas a reducer you are free (or rather cofree ;)) to write it the way you want.\nThe library will give you different schemes how the store is updated.  Now\nthere is only one `Redox.DSL`, but in near future there will be at least one\nmore using coroutines (similar to how\n[Thermite](https://github.com/paf31/purescript-thermite) updates react\ncomponent state). \n\n## Redox.DSL\n\nA DSL has to be interpreted in the `Aff` monad.  Since `Aff` has an instance of\n`MonadEff` this does not restrict you in any way.  Checkout tests how to write\nsynchronous and asynchronous commands\n\nIn general if your `DSL` is generated by a functor `C` (for commands):\n```purescript\ntype DSL = Free C\n```\nthen you have to find a functor `RunC eff` which pairs with `C`:\n```purescript\npair :: forall eff x y. C (x -\u003e y) -\u003e RunC eff x -\u003e Aff eff y\n```\nYou can deduce from `pair`'s type that if `C` is a sum type then `RunC` is\na product - that's how it interprets `C`.\n\nThen the interpreter has type:\n```purescript\ntype Interp eff a = Cofree (RunC eff)\n```\n\nThis give rise to a function\n```purescript\nrunInterp :: forall state. DSL(state -\u003e state) -\u003e RunC eff state -\u003e Aff eff state\nrunInterp cmds state = exploreM pair cmds $ mkInterp state\n```\n\nYou can feed this function into `Redox.DSL.dispatch`:\n```purescript\ndispatchS :: forall eff state. DSL(state -\u003e state) -\u003e Aff (redox :: Redox | eff) state\ndispatchS = Redox.DSL.dispatch (\\_ _ -\u003e pure unit) runInterp store\n```\n\nCheck out tests for an example or this\n[repo](https://github.com/coot/purescript-dsl-example).  However you can write\nan interpreter without `Cofree`, simply by using `State` to track the state, or\njust by hand.  The advantage of using `Cofree` is that whenever you will change\n`C` the compiler will force you to update `RunC` in compatible way.\n\n## Incremental updates\nThe `Redox.DSL.dispatch` function will dispatch changes to the store when the\n`Aff` computation resolves.  You may want to dispatch every node of your\ninterpreter i.e. when each DSL command is run in the `do` block`. For example\nif you try to \n```purescript\ndispatch do\n  cmd1 arg1\n  cmd2 arg2\n```\nThe `dispatch` will update the store when cmd2 finishes.  But you can build\nthis into the interpreter.  Since this is common, there is a function in `Redox.Utils` to\nmodify an interpreter of type `Cofree f a` so that it updates the store on\nevery step of the `Cofree` comonad:\n```purescript\nRedox.Utils.mkIncInterp\n  :: forall state f\n   . (Functor f)\n  =\u003e Store state\n  -\u003e Cofree f state\n  -\u003e Cofree f state\n```\nNote that this function will not dispatch subscriptions.  If you build that\ninto your interpreterer or you can use `dispatchP` which does not run\nsubscriptions (the `P` suffix stands for pure).\n```purescript\nRedox.DSL.dispatchP\n  :: forall state dsl eff\n   . (Error -\u003e Eff (redox :: REDOX | eff) Unit)\n  -\u003e (dsl -\u003e state -\u003e Aff (redox :: REDOX | eff) state)\n  -\u003e Store state\n  -\u003e dsl\n  -\u003e Eff (redox :: REDOX | eff) (Canceler (redox :: REDOX | eff))\n```\n\n## Store middlewares via hoisting Cofree\nYou can modify your interpreter using\n```purescript\nRedox.Utils.hoistCofree'\n  :: forall f state\n   . (Functor f)\n  =\u003e (f (Cofree f state) -\u003e f (Cofree f state))\n  -\u003e Cofree f state\n  -\u003e Cofree f state\n```\n\nThis is a version of `Control.Comonad.Cofree.hoistCofree` but here the first\nargument does not need to be a natural transformation.  This let you add\neffects to the interpreter.  For example `mkIncInterp` is build using it.\nAnother example is to add a logger.\n\n```purescript\naddLogger\n  :: forall state f\n   . (Functor f)\n  =\u003e Cofree f state\n  -\u003e Cofree f state\naddLogger interp = hoistCofree' nat interp\n  where\n    nat :: f (Cofree f state) -\u003e f (Cofree f state)\n    nat fa = g \u003c$\u003e fa\n\n    g :: Cofree f state -\u003e Cofree f state\n    g cof = unsafePerformEff do\n      -- Control.Comonad.Cofree.head \n      log $ unsafeCoerce (head cof)\n      pure cof\n```\n\nThere are plenty of other things you can do with the interpreter in this way, e.g.\nundo/redo stack, optimistic updates, crash reporting, delay actions (or\njust some actions, via prisms).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoot%2Fpurescript-redox","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcoot%2Fpurescript-redox","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcoot%2Fpurescript-redox/lists"}