{"id":13681446,"url":"https://github.com/kowainik/prolens","last_synced_at":"2025-08-19T13:15:44.489Z","repository":{"id":53782131,"uuid":"302875274","full_name":"kowainik/prolens","owner":"kowainik","description":"👓 Profunctor based lightweight implementation of Lenses","archived":false,"fork":false,"pushed_at":"2023-05-30T18:58:06.000Z","size":71,"stargazers_count":71,"open_issues_count":3,"forks_count":4,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-03-16T10:35:27.464Z","etag":null,"topics":["hacktoberfest","haskell","lens","lenses","prisms","profunctor-optics","profunctors","traversal"],"latest_commit_sha":null,"homepage":"","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kowainik.png","metadata":{"funding":{"ko_fi":"kowainik","github":["vrom911"]},"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null}},"created_at":"2020-10-10T10:23:56.000Z","updated_at":"2024-12-12T08:09:29.000Z","dependencies_parsed_at":"2023-10-12T06:04:51.222Z","dependency_job_id":null,"html_url":"https://github.com/kowainik/prolens","commit_stats":{"total_commits":34,"total_committers":4,"mean_commits":8.5,"dds":0.5294117647058824,"last_synced_commit":"5d0f9311c87f59b851f932e1e37b70d519f5c39e"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kowainik%2Fprolens","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kowainik%2Fprolens/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kowainik%2Fprolens/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kowainik%2Fprolens/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kowainik","download_url":"https://codeload.github.com/kowainik/prolens/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245611795,"owners_count":20643896,"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":["hacktoberfest","haskell","lens","lenses","prisms","profunctor-optics","profunctors","traversal"],"created_at":"2024-08-02T13:01:30.811Z","updated_at":"2025-03-26T07:32:04.943Z","avatar_url":"https://github.com/kowainik.png","language":"Haskell","funding_links":["https://ko-fi.com/kowainik","https://github.com/sponsors/vrom911"],"categories":["Haskell"],"sub_categories":[],"readme":"# prolens\n\n![Prolens Logo](https://user-images.githubusercontent.com/8126674/95865685-da91b080-0d5e-11eb-91cd-b6a7bae29262.png)\n\n[![GitHub CI](https://github.com/kowainik/prolens/workflows/CI/badge.svg)](https://github.com/kowainik/prolens/actions)\n[![Hackage](https://img.shields.io/hackage/v/prolens.svg?logo=haskell)](https://hackage.haskell.org/package/prolens)\n[![MPL-2.0 license](https://img.shields.io/badge/license-MPL--2.0-blue.svg)](LICENSE)\n\nThe `prolens` package is a Haskell library with a __minimal__ and\n__lightweight__ implementation of _optics_. __Optic__ is a high-level\nconcept for values that provide _composable_ access to different parts of\nstructures.\n\nProlens implements the following optics:\n\n* __Lens__ — composable getters and setters\n* __Prism__ — composable constructors and deconstructors\n* __Traversal__ — composable data structures visitors\n\n## Goals\n\nWe created the `prolens` project in pursuit of the following goals:\n\n1. __Education__. Teach others how to implement and work with\n   profunctor optics. This also means that some underlying types or\n   type variables have different unconventional names\n2. __Learning__. Explore new concepts ourselves and understand better\n   abstractions used in the implementation.\n3. __Minimalism__. Keep the number of dependencies, features and code\n   low, but still solve common problems.\n4. __Performance__. Despite being minimalist, implement optics so they\n   are as fast as manual and clumsy pattern matching.\n5. __Exploration__. Understand how different modern Haskell features\n   can work on improving interface and bring new flavour into standard\n   approaches. Because of this, we implement our own `Profunctor`\n   typeclass with the\n   [QuantifiedConstraints](https://downloads.haskell.org/ghc/latest/docs/html/users_guide/glasgow_exts.html#quantified-constraints)\n   feature, which is not present in any other library at the moment.\n6. __Profunctors__. We use profunctor encoding of optics because it\n   has more elegant design with fewer surprises.\n\n## Features\n\n1. __Lightweight__. Only\n   [base](http://hackage.haskell.org/package/base)\n   in dependencies. The project itself also has a rather small amount\n   of code.\n2. __Fast__. Despite being lightweight, `prolens` provides a\n   performant API. We use the\n   [inspection-testing](https://hackage.haskell.org/package/inspection-testing)\n   library to guarantee that our implementation of optics compiles to\n   the same code as plain Haskell getters, record-update syntax and\n   pattern matching.\n3. __Excellent documentation__. The `prolens` library contains a\n   mini-tutorial on optics, enough to understand how and when to use\n   basic lenses and prisms.\n4. __Beginner-friendly__. The abstractions in the implementation are\n   hardcore, but our documentation presents the concept in a\n   beginner-friendly and approachable manner.\n5. __Lawful__. We use property-based testing to make sure that laws of\n   all underlying abstractions are verified.\n\n## How to use\n\n`prolens` is compatible with the latest GHC compiler\nversions starting from `8.6.5`.\n\nIn order to start using `prolens` in your project, you\nwill need to set it up with the three easy steps:\n\n1. Add the dependency on `prolens` in your project's\n   `.cabal` file. For this, you should modify the `build-depends`\n   section by adding the name of this library. After the adjustment,\n   this section could look like this:\n\n   ```haskell\n   build-depends: base ^\u003e= 4.15\n                , prolens ^\u003e= LATEST_VERSION\n   ```\n2. In the module where you wish to use composable getters and setters,\n   you should add the import:\n\n   ```haskell\n   import Prolens (Lens', lens, view)\n   ```\n3. Now you can use the types and functions from the library:\n\n   ```haskell\n   data User = User\n       { userName :: String\n       , userAge  :: Int\n       }\n\n   nameL :: Lens' User String\n   nameL = lens userName (\\u new -\u003e u { userName = new })\n\n   main :: IO ()\n   main = putStrln $ view nameL (User \"Johnny\" 27)\n   ```\n\n### Usage with Stack\n\nIf `prolens` is not available on your current Stackage\nresolver yet, fear not! You can still use it from Hackage by adding\nthe following to the `extra-deps` section of your `stack.yaml` file:\n\n```yaml\nextra-deps:\n  - prolens-CURRENT_VERSION\n```\n\n## Comparison to other libraries\n\n1. [lens](https://hackage.haskell.org/package/lens)\n\n   It is the most mature Haskell library for optics. `lens` provides a\n   richer interface, but it is heavyweight and based on Van Laarhoven (VL)\n   encoding of lenses.\n\n2. [microlens](https://hackage.haskell.org/package/microlens)\n\n   A lightweight implementation of optics compatible with\n   `lens`. `microlens` is also minimalistic, but it doesn't provide\n   prisms and is based on VL encoding.\n\n3. [optics](https://hackage.haskell.org/package/optics)\n\n   The `optics` library uses the profunctor encoding. It provides much\n   more features than `prolens`, but at the same time it's\n   heavyweight. Also, `optics` uses an opaque representation of optics\n   (e.g. they are wrapped in a newtype), which means that they are\n   composed using the custom operator `%`, while in `prolens` optics\n   are type aliases to functions and can be easily composed with the\n   dot `.` operator.\n\n4. [profunctor-optics](https://hackage.haskell.org/package/profunctor-optics)\n\n   This library is also based on profunctor encoding (as the name\n   suggests) and provides optics as aliases to functions. But it is\n   more heavyweight, though it provides more features.\n\nIn addition to this per-library comparison, `prolens` has a few unique\nfeatures:\n\n  * Beginner-friendly documentation with usage examples\n  * Usage of `inspection-testing` to guarantee the performance of\n    optics\n  * Property-based tests of lens and typeclasses laws to make sure\n    that all abstractions behave properly\n\n## Acknowledgement\n\n  * Edward Kmett for lenses and profunctor typeclasses\n  * Well-Typed for the implementation of `optics`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkowainik%2Fprolens","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkowainik%2Fprolens","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkowainik%2Fprolens/lists"}