Add buniq to README

It's another perfectly legitimate way to construct an object!
This commit is contained in:
Tom Harding 2019-06-24 09:01:47 +01:00
parent 9c7b830bdc
commit 94171f3401

View File

@ -52,7 +52,9 @@ example data types:
{-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeApplications #-}
module Main where module Main where
import Control.Applicative (Alternative (empty))
import Control.Lens ((.~), (^.), (&), Const (..), Identity, anyOf) import Control.Lens ((.~), (^.), (&), Const (..), Identity, anyOf)
import Data.Barbie (ProductB (buniq))
import Data.Functor.Const (Const (..)) import Data.Functor.Const (Const (..))
import Data.Functor.Identity (Identity (..)) import Data.Functor.Identity (Identity (..))
import Data.Generic.HKD import Data.Generic.HKD
@ -178,14 +180,24 @@ eg7 = eg6 [1] [] ["Tom", "Tim"]
-- Triple [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 ### Field Access
The `field` lens, when given a type-applied field name, allows us to focus on The `field` lens, when given a type-applied field name, allows us to focus on
fields within a record: fields within a record:
```haskell ```haskell
eg8 :: Last Int eg9 :: Last Int
eg8 = eg0 ^. field @"age" eg9 = eg0 ^. field @"age"
-- Last {getLast = Nothing} -- Last {getLast = Nothing}
``` ```
@ -194,9 +206,9 @@ record (note that these set values will _also_ need to be in our functor of
choice): choice):
```haskell ```haskell
eg9 :: Partial User eg10 :: Partial User
eg9 = eg0 & field @"name" .~ pure "Evil Tom" eg10 = eg0 & field @"name" .~ pure "Evil Tom"
& field @"likesDogs" .~ pure False & field @"likesDogs" .~ pure False
-- User -- User
-- { name = Last {getLast = Just "Evil Tom"} -- { name = Last {getLast = Just "Evil Tom"}
-- , age = Last {getLast = Nothing} -- , 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: completed for a given partial type:
```haskell ```haskell
eg10 :: Bool eg11 :: Bool
eg10 = anyOf (field @"name") (isJust . getLast) eg0 eg11 = anyOf (field @"name") (isJust . getLast) eg0
-- False -- 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: doesn't exist in our type:
```{haskell, ignore} ```{haskell, ignore}
eg11 :: Identity () eg12 :: Identity ()
eg11 = eg3 ^. field @"oops" eg12 = eg3 ^. field @"oops"
-- error: -- error:
-- • The type User does not contain a field named 'oops'. -- • 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: product types:
```haskell ```haskell
eg12 :: Labels Triple eg13 :: Labels Triple
eg12 = mempty & position @1 .~ Const "hello" eg13 = mempty & position @1 .~ Const "hello"
& position @2 .~ Const "world" & position @2 .~ Const "world"
-- Triple -- Triple
-- Const "hello" -- 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: Again, this is a `Lens`, so we can just as easily _set_ values:
```haskell ```haskell
eg13 :: Partial User eg14 :: Partial User
eg13 = eg9 & position @2 .~ pure 25 eg14 = eg10 & position @2 .~ pure 25
-- User -- User
-- { name = Last {getLast = Just "Evil Tom"} -- { name = Last {getLast = Just "Evil Tom"}
-- , age = Last {getLast = Just 25} -- , 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: type errors are a delight:
```{haskell, ignore} ```{haskell, ignore}
eg14 :: Identity () eg15 :: Identity ()
eg14 = deconstruct @Identity triple ^. position @4 eg15 = deconstruct @Identity triple ^. position @4
-- error: -- error:
-- • The type Triple does not contain a field at position 4 -- • 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: this interface:
```haskell ```haskell
eg15 :: Labels User eg16 :: Labels User
eg15 = label eg16 = label
-- User -- User
-- { name = Const "name" -- { name = Const "name"
-- , age = Const "age" -- , 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: fields whose values satisfy some predicate:
```haskell ```haskell
eg16 :: [String] eg17 :: [String]
eg16 = labelsWhere (isNothing . getLast) eg9 eg17 = labelsWhere (isNothing . getLast) eg10
-- ["age"] -- ["age"]
``` ```