mini 1.4.0.0 → 1.4.0.1
raw patch · 3 files changed
+95/−6 lines, 3 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- CHANGELOG.md +4/−0
- Mini/Optics/Lens.hs +84/−0
- mini.cabal +7/−6
CHANGELOG.md view
@@ -1,3 +1,7 @@+1.4.0.1 [2024-10-27]+--------------------+* docs: Add 'Mini.Optics.Lens' tutorial+ 1.4.0.0 [2024-07-01] -------------------- * Mini.Transformers.ParserT:
Mini/Optics/Lens.hs view
@@ -12,6 +12,9 @@ view, over, set,++ -- * Tutorial+ -- $tutorial ) where import Control.Applicative (@@ -64,3 +67,84 @@ -- | Overwrite the field referenced by a lens with a value on a structure set :: Lens s t a b -> b -> s -> t set o b = runIdentity . o (const $ Identity b)++{-+ - Tutorial+ -}++{- $tutorial+Record syntax is excellent for modeling data. But modifying records can be+cumbersome, especially when nested. Below we define some data and compare common+ways of modifying it, illustrating the need for something better. Then we+satisfy that need with lenses, showing how to use them.++Lenses essentially take the place of accessor functions. The accessor names of+the records below start with an underscore; this is to avoid name clashing when+creating the corresponding lenses.++> data Parcel = Parcel+> { _weight :: Int+> , _size :: Size+> }+>+> data Size = Size+> { _length :: Int+> , _width :: Int+> , _height :: Int+> }++Let's create a function that doubles the width of a parcel and sets its weight+to 500. First using record syntax, then pattern matching.++> foo :: Parcel -> Parcel+> foo p =+> let s = _size p+> w = _width s+> in p+> { _weight = 500+> , _size = s{_width = w * 2}+> }+>+> foo' :: Parcel -> Parcel+> foo' (Parcel _ (Size l w h)) =+> Parcel+> 500+> (Size l (w * 2) h)++Record syntax lets us specify only the fields we wish to modify but we have to+use the accessors repeatedly. Pattern matching looks cleaner but we have to+unpack and repack all the data. It's not hard to imagine how unwieldy it would+be with heavily nested records no matter which way we choose.++Lenses provide a concise, declarative, composable way to inspect and modify+records. The downside is that some initial boilerplate code is required to+create the lenses.++> weight :: Lens Parcel Parcel Int Int+> weight = lens _weight $ \s b -> s{_weight = b}+>+> size :: Lens Parcel Parcel Size Size+> size = lens _size $ \s b -> s{_size = b}+>+> width :: Lens Size Size Int Int+> width = lens _width $ \s b -> s{_width = b}++Each lens can be used with 'view', 'over', and 'set' to inspect or modify a+field, letting us complete our task with ease.++> foo'' :: Parcel -> Parcel+> foo'' =+> over (size . width) (* 2)+> . set weight 500++Note the reversed ordering of the composed lenses. Inspecting is similar to+using regular accessors, but again, composed in reverse.++> bar :: Parcel -> Int+> bar = view (size . width)++This covers the most typical use case, where the lenses preserve the structure+of the records (e.g. @weight@ is a @Lens@ from @Parcel@ to @Parcel@, from @Int@+to @Int@). Creating lenses that change the structure is left as an exercise to+the reader.+-}
mini.cabal view
@@ -1,16 +1,17 @@ cabal-version: 2.4 name: mini-version: 1.4.0.0+version: 1.4.0.1 license: MIT license-file: LICENSE-copyright: (c) 2023-2024 Victor Wallsten-author: Victor Wallsten-maintainer: victor.wallsten@protonmail.com+author: Victor Wallsten <victor.wallsten@protonmail.com>+maintainer: Victor Wallsten <victor.wallsten@protonmail.com> homepage: https://gitlab.com/vicwall/mini bug-reports: https://gitlab.com/vicwall/mini/issues synopsis: Minimal essentials-description: A minimal yet powerful library of essentials, only depending on- @base@.+description:+ A minimal yet powerful library of essentials: data structures, lenses,+ transformers, and parsing. Uncompromisingly light on dependencies. Easily+ navigable code base, keeping indirection and clutter to a minimum. category: library tested-with: GHC == 9.4.8 extra-doc-files: CHANGELOG.md