@@ -3,25 +3,29 @@
4Status](https://travis-ci.org/kcsongor/generic-lens.svg?branch=master)](https://travis-ci.org/kcsongor/generic-lens)
4Status](https://travis-ci.org/kcsongor/generic-lens.svg?branch=master)](https://travis-ci.org/kcsongor/generic-lens)
6−Generically derive lenses for accessing fields of data types.
6+Generically derive lenses and prisms for data types.
8Available on [Hackage](https://hackage.haskell.org/package/generic-lens)
8Available on [Hackage](https://hackage.haskell.org/package/generic-lens)
10−This package uses the GHC 8 Generic representation to derive various operations on data structures with a lens interface, including structural subtype relationship between records and positional indexing into arbitrary product types.
10+This package uses the GHC 8 `Generic` representation to derive various operations
11+on data structures with lens interfaces, including structural subtype
12+relationships between records and positional indexing into arbitrary product
12−This is made possible by GHC-8's new Generics API, which provides the meta-data
15+This is made possible by GHC 8's new Generics API, which provides metadata
13−at the type-level (previously only value-level meta-data was available).
16+at the type-level (previously only value-level metadata was available).
15−An example can be found in the `examples` folder.
18+Examples can be found in the `examples` folder. This library makes heavy use of
19+[Visible Type Applications](https://ghc.haskell.org/trac/ghc/wiki/TypeApplication).
17−(The library makes heavy use of [Visible Type Applications](https://ghc.haskell.org/trac/ghc/wiki/TypeApplication))
21+## Lenses
19−## Record fields
23+### Record fields
21−Record fields can be accessed by their label.
25+Record fields can be accessed by their label:
24−data Person = Person { name :: String, age :: Int } deriving (Show, Generic)
28+data Person = Person { name :: String, age :: Int } deriving (Generic, Show)
26sally :: Person
30sally :: Person
27sally = Person "Sally" 25
31sally = Person "Sally" 25
@@ -32,30 +36,32 @@ sally = Person "Sally" 25
34>>> setField @"age" 26 sally
38>>> setField @"age" 26 sally
35−Person { name = "Sally", age = 26 }
39+Person {name = "Sally", age = 26}
37>>> sally ^. field @"name"
41>>> sally ^. field @"name"
40>>> sally & field @"name" .~ "Tamas"
44>>> sally & field @"name" .~ "Tamas"
41−Person { name = "Tamas", age = 25 }
45+Person {name = "Tamas", age = 25}
47+>>> sally ^. field @"pet"
49+ • The type Person does not contain a field named "pet"
45−## Positional fields
52+### Positional fields
47−Fields can be accessed by their position in the data structure (index starting at 1).
54+Fields can be accessed by their position in the data structure (index starting at 1):
50−data Point = Point Int Int Int deriving (Show, Generic)
57+data Point = Point Int Int Int deriving (Generic, Show)
51−data Polygon = Polygon Point Point Point deriving (Show, Generic)
58+data Polygon = Polygon Point Point Point deriving (Generic, Show)
53polygon :: Polygon
60polygon :: Polygon
54polygon = Polygon (Point 1 5 3) (Point 2 4 2) (Point 5 7 (-2))
61polygon = Polygon (Point 1 5 3) (Point 2 4 2) (Point 5 7 (-2))
59>>> getPosition @2 polygon
65>>> getPosition @2 polygon
60Point 2 4 2
66Point 2 4 2
@@ -68,19 +74,51 @@ Polygon (Point 26 5 3) (Point 2 4 2) (Point 5 7 (-2))
68>>> polygon & position @3 . position @2 %~ (+10)
74>>> polygon & position @3 . position @2 %~ (+10)
69Polygon (Point 1 5 3) (Point 2 4 2) (Point 5 17 (-2))
75Polygon (Point 1 5 3) (Point 2 4 2) (Point 5 17 (-2))
77+>>> polygon ^. position @10
79+ • The type Polygon does not contain a field at position 10
73−Since tuples are an instance of Generic, positional lenses can be used with them.
82+Since tuples are an instance of `Generic`, they also have positional lenses:
76>>> (("hello", True), 5) ^. position @1 . position @2
85>>> (("hello", True), 5) ^. position @1 . position @2
80−## Typed fields
89+### Typed fields
91+Fields can be accessed by their type in the data structure, assuming that this
95+data Person = Person { name :: String, age :: Int } deriving (Generic, Show)
96+data Point = Point Int Int Int deriving (Generic, Show)
99+sally = Person "Sally" 25
106+>>> getTyped @String sally
109+>>> setTyped @Int sally 26
110+Person {name = "Sally", age = 26}
112+>>> point ^. typed @Int
114+ • The type Point contains multiple values of type Int; the choice of value is thus ambiguous
116+>>> point & typed @String .~ "Point"
118+ • The type Point does not contain a value of type [Char]
83−## Structural subtyping
121+### Structural subtyping
85A record is a (structural) `subtype' of another, if its fields are a superset of
123A record is a (structural) `subtype' of another, if its fields are a superset of
86those of the other.
124those of the other.
@@ -98,7 +136,7 @@ data Animal = Animal
98 } deriving (Generic, Show)
136 } deriving (Generic, Show)
100human :: Human
138human :: Human
101−human = Human { name = "Tunyasz", age = 50, address = "London" }
139+human = Human {name = "Tunyasz", age = 50, address = "London"}
104```haskell
142```haskell
@@ -126,6 +164,77 @@ growUp (Animal name age) = Animal name (age + 50)
126Human {name = "Tunyasz", age = 60, address = "London"}
164Human {name = "Tunyasz", age = 60, address = "London"}
169+### Named constructors
171+Constructor components can be accessed using the constructor's name:
177+data Dog = MkDog { name :: Name, age :: Age } deriving (Generic, Show)
178+data Animal = Dog Dog | Cat (Name, Age) | Duck Age deriving (Generic, Show)
180+shep = Dog (MkDog "Shep" 4)
186+>>> shep ^? _Ctor @"Dog"
187+Just (MkDog {name = "Shep", age = 4})
189+>>> shep ^? _Ctor @"Cat"
192+>>> mog ^? _Ctor @"Cat"
195+>>> _Ctor @"Cat" # ("Garfield", 6) :: Animal
198+>>> donald ^? _Ctor @"Giraffe"
200+ • The type Animal does not contain a constructor named "Giraffe"
203+## Typed constructors
205+Constructor components can be accessed using the component's type, assuming
206+that this type is unique:
212+data Dog = MkDog { name :: Name, age :: Age } deriving (Generic, Show)
213+data Animal = Dog Dog | Cat (Name, Age) | Duck Age deriving (Generic, Show)
215+shep = Dog (MkDog "Shep" 4)
221+>>> mog ^? _Typed @Dog
224+>>> shep ^? _Typed @Dog
225+Just (MkDog {name = "Shep", age = 4})
227+>>> donald ^? _Typed @Age
230+>>> donald ^? _Typed @Float
232+ • The type Animal does not contain a constructor whose field is of type Float
234+>>> _Typed @Age # 6 :: Animal
129## Contributors
238## Contributors
131+ [Toby Shaw](https://github.com/TobyShaw)
240+ [Toby Shaw](https://github.com/TobyShaw)