{"id":18737041,"url":"https://github.com/higherkindness/droste","last_synced_at":"2025-05-15T09:02:27.439Z","repository":{"id":33044155,"uuid":"117213612","full_name":"higherkindness/droste","owner":"higherkindness","description":"recursion schemes for cats; to iterate is human, to recurse, divine","archived":false,"fork":false,"pushed_at":"2025-04-23T11:55:54.000Z","size":1554,"stargazers_count":390,"open_issues_count":17,"forks_count":52,"subscribers_count":26,"default_branch":"main","last_synced_at":"2025-05-13T03:44:08.830Z","etag":null,"topics":["functional-programming","recursion-schemes","scala"],"latest_commit_sha":null,"homepage":"","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/higherkindness.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","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":"AUTHORS.md","dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-01-12T08:17:00.000Z","updated_at":"2025-05-04T20:37:43.000Z","dependencies_parsed_at":"2023-02-18T04:00:37.269Z","dependency_job_id":"5f7ce451-82f7-4ea2-a76d-dbc0e9b5c373","html_url":"https://github.com/higherkindness/droste","commit_stats":{"total_commits":431,"total_committers":33,"mean_commits":13.06060606060606,"dds":0.5150812064965198,"last_synced_commit":"55e2bb687bd3abced0e061be3fc9dea359f97605"},"previous_names":["andyscott/droste"],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/higherkindness%2Fdroste","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/higherkindness%2Fdroste/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/higherkindness%2Fdroste/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/higherkindness%2Fdroste/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/higherkindness","download_url":"https://codeload.github.com/higherkindness/droste/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254310510,"owners_count":22049468,"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":["functional-programming","recursion-schemes","scala"],"created_at":"2024-11-07T15:23:28.359Z","updated_at":"2025-05-15T09:02:27.408Z","avatar_url":"https://github.com/higherkindness.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cimg align=\"right\" src=\"logos/droste_cocoa.png\" height=\"200px\" style=\"padding-left: 20px\"/\u003e\n\n# Droste\n\n[![Join the chat at https://gitter.im/higherkindness/droste](https://badges.gitter.im/higherkindness/droste.svg)](https://gitter.im/higherkindness/droste?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge)\n\nDroste is a recursion library for Scala.\n\n**SBT installation**\n\nSelect a tagged release version (`x.y.z`) and then add the following\nto your SBT build:\n\n```scala\nlibraryDependencies += \"io.higherkindness\" %% \"droste-core\" % \"x.y.z\"\n```\n\n# Usage\n\nDroste makes it easy to assemble morphisms. For example, calculating\nFibonacci values can be done with a histomorphism if we model natural\nnumbers as a chain of `Option`. We can easily unfold with an\nanamorphism and then fold to our result with a histomorphism.\n\n```scala\nimport higherkindness.droste._\nimport higherkindness.droste.data._\n\nval natCoalgebra: Coalgebra[Option, BigDecimal] =\n  Coalgebra(n =\u003e if (n \u003e 0) Some(n - 1) else None)\n\nval fibAlgebra: CVAlgebra[Option, BigDecimal] = CVAlgebra {\n  case Some(r1 :\u003c Some(r2 :\u003c _)) =\u003e r1 + r2\n  case Some(_ :\u003c None)           =\u003e 1\n  case None                      =\u003e 0\n}\n\nval fib: BigDecimal =\u003e BigDecimal = scheme.ghylo(\n  fibAlgebra.gather(Gather.histo),\n  natCoalgebra.scatter(Scatter.ana))\n```\n\n```scala\nfib(0)\n// res0: BigDecimal = 0\nfib(1)\n// res1: BigDecimal = 1\nfib(2)\n// res2: BigDecimal = 1\nfib(10)\n// res3: BigDecimal = 55\nfib(100)\n// res4: BigDecimal = 354224848179261915075\n```\n\nAn anamorphism followed by a histomorphism is also known as a\ndynamorphism. Recursion scheme animals like dyna are available\nin the zoo:\n\n```scala\n\nval fibAlt: BigDecimal =\u003e BigDecimal =\n  scheme.zoo.dyna(fibAlgebra, natCoalgebra)\n```\n\n```scala\nfibAlt(0)\n// res5: BigDecimal = 0\nfibAlt(1)\n// res6: BigDecimal = 1\nfibAlt(2)\n// res7: BigDecimal = 1\nfibAlt(10)\n// res8: BigDecimal = 55\nfibAlt(100)\n// res9: BigDecimal = 354224848179261915075\n```\n\nWhat if we want to do two things at once? Let's calculate a\nFibonacci value and the sum of all squares.\n\n```scala\nval fromNatAlgebra: Algebra[Option, BigDecimal] = Algebra {\n  case Some(n) =\u003e n + 1\n  case None    =\u003e 0\n}\n\n// note: n is the fromNatAlgebra helper value from the previous level of recursion\nval sumSquaresAlgebra: RAlgebra[BigDecimal, Option, BigDecimal] = RAlgebra {\n  case Some((n, value)) =\u003e value + (n + 1) * (n + 1)\n  case None             =\u003e 0\n}\n\nval sumSquares: BigDecimal =\u003e BigDecimal = scheme.ghylo(\n  sumSquaresAlgebra.gather(Gather.zygo(fromNatAlgebra)),\n  natCoalgebra.scatter(Scatter.ana))\n```\n\n```scala\nsumSquares(0)\n// res10: BigDecimal = 0\nsumSquares(1)\n// res11: BigDecimal = 1\nsumSquares(2)\n// res12: BigDecimal = 5\nsumSquares(10)\n// res13: BigDecimal = 385\nsumSquares(100)\n// res14: BigDecimal = 338350\n```\n\nNow we can zip the two algebras into one so that we calculate\nboth results in one pass.\n\n```scala\nval fused: BigDecimal =\u003e (BigDecimal, BigDecimal) =\n  scheme.ghylo(\n    fibAlgebra.gather(Gather.histo) zip\n    sumSquaresAlgebra.gather(Gather.zygo(fromNatAlgebra)),\n    natCoalgebra.scatter(Scatter.ana))\n```\n\n```scala\nfused(0)\n// res15: (BigDecimal, BigDecimal) = (0, 0)\nfused(1)\n// res16: (BigDecimal, BigDecimal) = (1, 1)\nfused(2)\n// res17: (BigDecimal, BigDecimal) = (1, 5)\nfused(10)\n// res18: (BigDecimal, BigDecimal) = (55, 385)\nfused(100)\n// res19: (BigDecimal, BigDecimal) = (354224848179261915075, 338350)\n```\n\nDroste includes [athema](athema), a math expression parser/processor,\nas a more extensive example of recursion schemes.\n\n\u003cimg align=\"right\" src=\"logos/droste_psychedelic_1.png\" height=\"85px\" style=\"padding-left: 5px\"/\u003e\n\n# Credits\n\nA substantial amount of Droste's code is a derivation-- or an\nalternative encoding-- of patterns pioneered by others. Droste has\nbenefited from the excellent work in many other recursion libraries,\nblog posts, academic papers, etc. Notably, Droste has benefited from:\n\n- [recursion-schemes](https://github.com/ekmett/recursion-schemes)\n- [Matryoshka](https://github.com/slamdata/matryoshka)\n\nThank you to everyone involved. Additionally, thanks to Greg Pfeil\n(@sellout) for answering my random questions over the last few years\nwhile I've been slowly learning (and using recursion) schemes.\n\n\u003cimg align=\"right\" src=\"logos/droste_psychedelic_2.png\" height=\"85px\" style=\"padding-left: 5px\"/\u003e\n\n# Copyright and License\n\nCopyright the maintainers, 2018-present.\n\nAll code is available to you under the Apache License, Version 2.0,\navailable at http://www.apache.org/licenses/LICENSE-2.0.\n\nLogos provided by the very excellent [@impurepics](https://twitter.com/impurepics).\n\n# Disclamer\n\nPlease be advised that I have no idea what I am doing.\nNevertheless, this project is already being used for real\nwork with real data in real life.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhigherkindness%2Fdroste","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhigherkindness%2Fdroste","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhigherkindness%2Fdroste/lists"}