diff --git a/README.md b/README.md index e844e1e..fdc3afe 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,9 @@ example data types: {-# LANGUAGE TypeApplications #-} module Main where +import Control.Applicative (Alternative (empty)) import Control.Lens ((.~), (^.), (&), Const (..), Identity, anyOf) +import Data.Barbie (ProductB (buniq)) import Data.Functor.Const (Const (..)) import Data.Functor.Identity (Identity (..)) import Data.Generic.HKD @@ -178,14 +180,24 @@ eg7 = eg6 [1] [] ["Tom", "Tim"] -- Triple [1] [] ["Tom","Tim"] ``` +If you're _still_ not satisfied, check out the +[`buniq`](https://hackage.haskell.org/package/barbies-1.1.2.1/docs/Data-Barbie.html#v:buniq) +method hiding in `barbies`: + +```haskell +eg8 :: HKD Triple [] +eg8 = buniq empty +-- Triple [] [] [] +``` + ### Field Access The `field` lens, when given a type-applied field name, allows us to focus on fields within a record: ```haskell -eg8 :: Last Int -eg8 = eg0 ^. field @"age" +eg9 :: Last Int +eg9 = eg0 ^. field @"age" -- Last {getLast = Nothing} ``` @@ -194,9 +206,9 @@ record (note that these set values will _also_ need to be in our functor of choice): ```haskell -eg9 :: Partial User -eg9 = eg0 & field @"name" .~ pure "Evil Tom" - & field @"likesDogs" .~ pure False +eg10 :: Partial User +eg10 = eg0 & field @"name" .~ pure "Evil Tom" + & field @"likesDogs" .~ pure False -- User -- { name = Last {getLast = Just "Evil Tom"} -- , age = Last {getLast = Nothing} @@ -208,8 +220,8 @@ This also means, for example, we can check whether a particular value has been completed for a given partial type: ```haskell -eg10 :: Bool -eg10 = anyOf (field @"name") (isJust . getLast) eg0 +eg11 :: Bool +eg11 = anyOf (field @"name") (isJust . getLast) eg0 -- False ``` @@ -218,8 +230,8 @@ Finally, thanks to the fact that this library exploits some of the internals of doesn't exist in our type: ```{haskell, ignore} -eg11 :: Identity () -eg11 = eg3 ^. field @"oops" +eg12 :: Identity () +eg12 = eg3 ^. field @"oops" -- error: -- • The type User does not contain a field named 'oops'. ``` @@ -230,8 +242,8 @@ Just as with field names, we can use positions when working with non-record product types: ```haskell -eg12 :: Labels Triple -eg12 = mempty & position @1 .~ Const "hello" +eg13 :: Labels Triple +eg13 = mempty & position @1 .~ Const "hello" & position @2 .~ Const "world" -- Triple -- Const "hello" @@ -242,8 +254,8 @@ eg12 = mempty & position @1 .~ Const "hello" Again, this is a `Lens`, so we can just as easily _set_ values: ```haskell -eg13 :: Partial User -eg13 = eg9 & position @2 .~ pure 25 +eg14 :: Partial User +eg14 = eg10 & position @2 .~ pure 25 -- User -- { name = Last {getLast = Just "Evil Tom"} -- , age = Last {getLast = Just 25} @@ -255,8 +267,8 @@ Similarly, the internals here come to us courtesy of `generic-lens`, so the type errors are a delight: ```{haskell, ignore} -eg14 :: Identity () -eg14 = deconstruct @Identity triple ^. position @4 +eg15 :: Identity () +eg15 = deconstruct @Identity triple ^. position @4 -- error: -- • The type Triple does not contain a field at position 4 ``` @@ -268,8 +280,8 @@ names of the fields into the functor we're using. The `label` value gives us this interface: ```haskell -eg15 :: Labels User -eg15 = label +eg16 :: Labels User +eg16 = label -- User -- { name = Const "name" -- , age = Const "age" @@ -284,8 +296,8 @@ can implement functions such as `labelsWhere`, which returns the names of all fields whose values satisfy some predicate: ```haskell -eg16 :: [String] -eg16 = labelsWhere (isNothing . getLast) eg9 +eg17 :: [String] +eg17 = labelsWhere (isNothing . getLast) eg10 -- ["age"] ```