{"id":17251091,"url":"https://github.com/fumieval/data-functor-logistic","last_synced_at":"2025-04-14T05:20:13.168Z","repository":{"id":66326211,"uuid":"428282723","full_name":"fumieval/data-functor-logistic","owner":"fumieval","description":null,"archived":false,"fork":false,"pushed_at":"2023-06-11T03:35:16.000Z","size":7,"stargazers_count":8,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-27T19:08:47.760Z","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":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fumieval.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"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":"2021-11-15T13:50:25.000Z","updated_at":"2023-05-29T06:46:24.000Z","dependencies_parsed_at":null,"dependency_job_id":"6cbaa7ab-6fb8-4baa-9be5-bcc7040b25cc","html_url":"https://github.com/fumieval/data-functor-logistic","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/fumieval%2Fdata-functor-logistic","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fumieval%2Fdata-functor-logistic/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fumieval%2Fdata-functor-logistic/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fumieval%2Fdata-functor-logistic/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fumieval","download_url":"https://codeload.github.com/fumieval/data-functor-logistic/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248824914,"owners_count":21167388,"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-15T06:50:18.461Z","updated_at":"2025-04-14T05:20:13.153Z","avatar_url":"https://github.com/fumieval.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"Logistic is to setters as Distributive is to getters\n----\n\nDistributive functors are containers where getters can be enumerated as their own types.\n\nThis is the definition of the `Distributive` class:\n\n```haskell\nclass Functor g =\u003e Distributive g where\n  distribute :: Functor f =\u003e f (g a) -\u003e g (f a)\n```\n\nOne easy-to-understand instance is `Complex`.\n\n```haskell\ndata Complex a = !a :+ !a\n\nrealPart :: Complex a -\u003e a\nrealPart (x :+ _) =  x\n\nimagPart :: Complex a -\u003e a\nimagPart (_ :+ y) =  y\n\ninstance Distributive Complex where\n  distribute wc = fmap realPart wc :+ fmap imagPart wc\n```\n\nGiven any functor-wrapped value, `distribute` fmaps the getters of `Complex` to it.\n`distribute id` instantiates it as the function (`(-\u003e) r`) functor. In this case, `distribute id` is equal to `realPart :+ imagPart`.\n\nHowever, we cannot modify the elements this way because `distribute` passes getters but not setters.\n\nHere we introduce a new `Logistic` class to provide settability to containers:\n\n```haskell\nclass Functor t =\u003e Logistic t where\n  deliver :: Contravariant f =\u003e f (t a -\u003e t a) -\u003e t (f (a -\u003e a))\n```\n\nWhile the type of `deliver` is slightly more intimidating, it's actually very close to the `distribute`;\nthe `Functor` constraint is `Contravariant` instead and the contents are endomorphisms.\n\nHere's the instance for `Complex`. `deliver f` contramaps a setter function to `f` for each field:\n\n```haskell\ninstance Logistic Complex where\n  deliver f\n    = contramap (\\g (a :+ b) -\u003e g a :+ b) f\n    :+ contramap (\\g (a :+ b) -\u003e a :+ g b) f\n ```\n\nInstantiating the `Op` contravariant functor, it is trivial to obtain a collection of setters.\n\n```haskell\nnewtype Op a b = Op { getOp :: b -\u003e a }\n\nsetters :: Logistic t =\u003e t ((a -\u003e a) -\u003e t a -\u003e t a)\nsetters = getOp \u003c$\u003e deliver (Op id)\n```\n\n```haskell\nghci\u003e let setR :+ setI = setters\nghci\u003e setR (+1) (0 :+ 1)\n1 :+ 1\nghci\u003e setI (+1) (0 :+ 1)\n0 :+ 2\n```\n\n`deliver` has a generic default implementation which works for any single-constructor products.\n\nThis class can be useful to complement `Distributive`. Generalisation to higher-kinded data would also be interesting.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffumieval%2Fdata-functor-logistic","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffumieval%2Fdata-functor-logistic","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffumieval%2Fdata-functor-logistic/lists"}