{"id":20132518,"url":"https://github.com/aherrmann/haskellmapfilterm","last_synced_at":"2025-06-10T10:06:21.003Z","repository":{"id":23362893,"uuid":"26724025","full_name":"aherrmann/HaskellMapFilterM","owner":"aherrmann","description":"Benchmark different implementations of filterM on a Map in Haskell","archived":false,"fork":false,"pushed_at":"2014-11-16T18:56:33.000Z","size":364,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-02T22:18:27.862Z","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/aherrmann.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-11-16T18:46:52.000Z","updated_at":"2019-12-05T06:33:41.000Z","dependencies_parsed_at":"2022-08-30T17:40:49.931Z","dependency_job_id":null,"html_url":"https://github.com/aherrmann/HaskellMapFilterM","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/aherrmann%2FHaskellMapFilterM","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aherrmann%2FHaskellMapFilterM/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aherrmann%2FHaskellMapFilterM/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aherrmann%2FHaskellMapFilterM/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aherrmann","download_url":"https://codeload.github.com/aherrmann/HaskellMapFilterM/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aherrmann%2FHaskellMapFilterM/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":257285432,"owners_count":22521196,"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-11-13T20:53:52.854Z","updated_at":"2025-06-10T10:06:20.972Z","avatar_url":"https://github.com/aherrmann.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Benchmark on monadic filtering on a map in Haskell\n\nThe module `Data.Map` (henceforth `M`) offers a filter function for map\ncontainers which takes a pure function predicate and a map, and returns a new\nmap with all the elements removed on which the predicate is not true. However,\nit does not offer a function like `filterM`, which takes a monadic predicate\nand returns a filtered map in a monad.\n\nThe file [`benchmark.hs`](benchmark.hs) contains a few possible implementations\nof such a function `filterM` on maps. Furthermore, the file\n[`MapWithFilterM.hs`](MapWithFilterM.hs) contains a modified version of the\nmodule `M` (henceforth `M'`) which includes an implementation of `filterM` that\nworks on the map's internal representation to avoid conversion-overhead.\n\n## The Data\n\nA performance comparison between all these implementations can be found in the\nfile\n[`bench.html`](http://htmlpreview.github.io/?https://github.com/aherrmann/HaskellMapFilterM/blob/master/bench.html).\nIt was created with the\n[criterion](https://hackage.haskell.org/package/criterion) package.\n\nA list of the methods that were benchmarked follows:\n\n  * `M.filter`: Use the built-in filter which takes a pure predicate. Useful\n    for comparison. \n  * `toAscList`: Round-trip through an ascending list of elements, and use\n    `filterM` on that list.\n  * `toList`: Same as `toAscList` just with a not-necessarily ascending list.\n  * `foldr`: Use `M.foldrWithKey` to construct a new map into which we add\n    items if the monadic predicate is true.\n  * `foldl`: Same as `foldr` but use a left-fold instead.\n  * `maybe`: Use the traversable instance of `M.Map` to first translate every\n    element `v` into either `Nothing` or `Just v` depending on the monadic\n    predicate, then filter the `Nothing`s out, and finally apply `fromJust` to\n    every element.\n  * `M'.filter`: Is the same as the above `M.filter` just on the modified map\n    module. Again, mainly for comparison.\n  * `M'.filterM`: Use an implementation that works right on the internal\n    representation of the map. Hence, it avoids conversions to lists and\n    reconstruction of the map from scratch.\n\nThe fastest among the above is `M.filter`. Next up are `toList`/`toAscList`.\nSurprisingly, `M'.filterM` does no better than `foldr`/`foldl`. And the slowest\nis `maybe`.\n\n## Conclusion\n\nIf you can use a pure predicate then use `M.filter`. If you have an inherently\nmonadic predicate then round-trip through a list with either `M.toAscList`, or\n`M.toList` it doesn't matter much.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faherrmann%2Fhaskellmapfilterm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faherrmann%2Fhaskellmapfilterm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faherrmann%2Fhaskellmapfilterm/lists"}