Skip to content

Commit a6a4f3c

Browse files
committed
Improve documentation and examples
1 parent 6b1cf4e commit a6a4f3c

File tree

1 file changed

+56
-66
lines changed

1 file changed

+56
-66
lines changed

src/Deriving/Aeson/Stripped.hs

Lines changed: 56 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,10 @@ import qualified Fcf
6262
import qualified GHC.TypeLits as Error
6363

6464

65-
-- | A newtype wrapper which provides 'FromJSON' / 'ToJSON' instances with a specific set
66-
-- of 'Options' (see the "Deriving.Aeson" module), and the ability to strip one or more
67-
-- fields from the JSON output, recovered at decode-time using some default values.
65+
-- | A newtype wrapper which provides 'FromJSON' / 'ToJSON' instances based on a specific
66+
-- set of 'AesonOptions' (see the "Deriving.Aeson" module), and the ability to strip one
67+
-- or more fields from the JSON output, recovered when decoding using some default
68+
-- `RecoverableValue`s.
6869
newtype StrippedJSON (fds :: [Type]) (opts :: [Type]) a
6970
= StrippedJSON { unStrippedJSON :: a }
7071

@@ -113,13 +114,13 @@ instance
113114

114115
-- | A field to be stripped from record values, identified by its @name@.
115116
--
116-
-- The @def@ value is used to recover the field at decode-time (see 'RecoverableValue').
117+
-- The @def@ value is used to recover the field when decoding (see 'RecoverableValue').
117118
data RField (name :: Symbol) (def :: k)
118119

119120
-- | A field to be stripped from non-record single-constructor values,
120121
-- identified by its __zero-based__ @position@ in the data constructor.
121122
--
122-
-- The @def@ value is used to recover the field at decode-time (see 'RecoverableValue').
123+
-- The @def@ value is used to recover the field when decoding (see 'RecoverableValue').
123124
data CField (position :: Nat) (def :: k)
124125

125126

@@ -204,8 +205,8 @@ data FromList (xs :: [k])
204205

205206
-- | Recovers a 'Monoid' value using 'mempty'.
206207
--
207-
-- >>> recoverValue (Proxy @(Pure 1)) :: Maybe Int
208-
-- Just 1
208+
-- >>> recoverValue (Proxy @Mempty) :: [Int]
209+
-- []
209210
data Mempty
210211

211212
-- | Recovers an 'Applicative' value using 'pure'.
@@ -215,7 +216,7 @@ data Mempty
215216
data Pure (x :: k)
216217

217218

218-
-- | A default field value which can be recovered at decode-time.
219+
-- | A default field value which can be recovered when decoding.
219220
class RecoverableValue (x :: k) (a :: Type) where
220221
-- | Recovers a default field value from the type-level.
221222
recoverValue :: Proxy x -> a
@@ -401,6 +402,7 @@ instance Monoid m => RecoverableValue Mempty m where
401402
--
402403
-- >>> :set -XDataKinds
403404
-- >>> :set -XDeriveGeneric
405+
-- >>> :set -XDerivingVia
404406
-- >>> :set -XGeneralizedNewtypeDeriving
405407
-- >>> :set -XOverloadedStrings
406408
-- >>> :set -XTypeApplications
@@ -418,94 +420,82 @@ instance Monoid m => RecoverableValue Mempty m where
418420
--
419421
-- >>> :{
420422
-- data RecordTest = RecordTest
421-
-- { testNumber :: {-# UNPACK #-} !Int
423+
-- { testBool :: !Bool
424+
-- , testNumber :: {-# UNPACK #-} !Int
422425
-- , testNewtype :: !WrappedInt
423426
-- , testString :: String
424427
-- , testIsString :: !Text
425428
-- , testList :: ![Int]
426-
-- , testIsList :: (Set.Set Int)
427-
-- , testMonoid :: ![Int]
429+
-- , testIsList :: Set.Set Int
430+
-- , testMonoid :: !Ordering
431+
-- , testValue :: Double
428432
-- }
429433
-- deriving (Generic, Show)
434+
-- deriving (FromJSON, ToJSON)
435+
-- via StrippedJSON
436+
-- '[ RField "testBool" 'False
437+
-- , RField "testIsList" (FromList '[ 13, 14, 13 ])
438+
-- , RField "testIsString" (FromString "text")
439+
-- , RField "testList" '[ 10, 11, 12 ]
440+
-- , RField "testMonoid" Mempty
441+
-- , RField "testNewtype" (Coerce 42 Int)
442+
-- , RField "testNumber" 7
443+
-- , RField "testString" "string"
444+
-- ]
445+
-- '[]
446+
-- RecordTest
430447
-- :}
431448
--
432-
-- >>> :{
433-
-- type StrippedRecordFields =
434-
-- '[ RField "testNumber" 7
435-
-- , RField "testNewtype" (Coerce 42 Int)
436-
-- , RField "testString" "string"
437-
-- , RField "testIsString" (FromString "text")
438-
-- , RField "testList" '[ 10, 11, 12 ]
439-
-- , RField "testIsList" (FromList '[ 13, 14, 13 ])
440-
-- , RField "testMonoid" Mempty
441-
-- ]
442-
-- :}
449+
-- Note that the order of the `RField` instructions does not matter ..
450+
--
451+
-- >>> let recordTest = RecordTest True 1 (WrappedInt 2) "s" "t" [1..3] (Set.fromList [4..6]) GT 3.14
443452
--
444453
-- >>> :{
445454
-- data NonRecordTest
446-
-- = NonRecordTest (Either String Int) (Maybe Int) ![Int] (Bool, Char, Int)
455+
-- = NonRecordTest () (Either String Int) (Maybe Int) ![Int] (Bool, Char, Int)
447456
-- deriving (Generic, Show)
457+
-- deriving (FromJSON, ToJSON)
458+
-- via StrippedJSON
459+
-- '[ CField 0 '()
460+
-- , CField 1 ('Left "test")
461+
-- , CField 3 (Pure 7)
462+
-- , CField 2 'Nothing
463+
-- , CField 4 '( 'False, "z", 42 )
464+
-- ]
465+
-- '[]
466+
-- NonRecordTest
448467
-- :}
449468
--
450-
-- >>> :{
451-
-- type StrippedNonRecordFields =
452-
-- '[ CField 0 ('Left "test")
453-
-- , CField 2 (Pure 7)
454-
-- , CField 1 'Nothing
455-
-- , CField 3 '( 'False, "z", 42 )
456-
-- ]
457-
-- :}
469+
-- .. nor does the order of the `CField` instructions.
470+
--
471+
-- >>> let nonRecordTest = NonRecordTest () (Right 1) (Just 2) [3..5] (True, 'a', 6)
458472

459473
-- $examples
460474
--
461475
-- === Stripping fields in a record value: ..
462476
--
463-
-- >>> :{
464-
-- encode
465-
-- $ StrippedJSON @StrippedRecordFields @'[]
466-
-- $ RecordTest 1 (WrappedInt 2) "s" "t" [1..3] (Set.fromList [4..6]) [7..9]
467-
-- :}
468-
-- "[]"
477+
-- >>> encode recordTest
478+
-- "{\"testValue\":3.14}"
469479
--
470480
-- === .. and recovering them when decoding using the specified defaults:
471481
--
472-
-- >>> :{
473-
-- fmap unStrippedJSON
474-
-- $ decode @(StrippedJSON StrippedRecordFields '[] RecordTest)
475-
-- $ encode
476-
-- $ StrippedJSON @StrippedRecordFields @'[]
477-
-- $ RecordTest 1 (WrappedInt 2) "s" "t" [1..3] (Set.fromList [4..6]) [7..9]
478-
-- :}
479-
-- Just (RecordTest {testNumber = 7, testNewtype = WrappedInt 42, testString = "string", testIsString = "text", testList = [10,11,12], testIsList = fromList [13,14], testMonoid = []})
482+
-- >>> decode @RecordTest $ encode recordTest
483+
-- Just (RecordTest {testBool = False, testNumber = 7, testNewtype = WrappedInt 42, testString = "string", testIsString = "text", testList = [10,11,12], testIsList = fromList [13,14], testMonoid = EQ, testValue = 3.14})
480484
--
481485
-- === Stripping fields in a non-record value: ..
482-
-- >>> :{
483-
-- encode
484-
-- $ StrippedJSON @StrippedNonRecordFields @'[]
485-
-- $ NonRecordTest (Right 1) (Just 2) [3..5] (True, 'a', 6)
486-
-- :}
486+
-- >>> encode nonRecordTest
487487
-- "[]"
488488
--
489489
-- === .. and recovering them when decoding using the specified defaults:
490490
--
491-
-- >>> :{
492-
-- fmap unStrippedJSON
493-
-- $ decode @(StrippedJSON StrippedNonRecordFields '[] NonRecordTest)
494-
-- $ encode
495-
-- $ StrippedJSON @StrippedNonRecordFields @'[]
496-
-- $ NonRecordTest (Right 1) (Just 2) [3..5] (True, 'a', 6)
497-
-- :}
498-
-- Just (NonRecordTest (Left "test") Nothing [7] (False,'z',42))
491+
-- >>> decode @NonRecordTest $ encode nonRecordTest
492+
-- Just (NonRecordTest () (Left "test") Nothing [7] (False,'z',42))
499493
--
500494
-- === Specifying encoding / decoding options:
501495
--
502496
-- The second parameter to 'StrippedJSON' works exactly the same as the only parameter
503-
-- to 'CustomJSON' (from the
504-
-- [deriving-aeson](http://hackage.haskell.org/package/deriving-aeson) package).
497+
-- to 'CustomJSON' from the
498+
-- [deriving-aeson](http://hackage.haskell.org/package/deriving-aeson) package.
505499
--
506-
-- >>> :{
507-
-- encode
508-
-- $ StrippedJSON @'[] @'[ FieldLabelModifier CamelToSnake ]
509-
-- $ RecordTest 1 (WrappedInt 2) "s" "t" [1..3] (Set.fromList [4..6]) [7..9]
510-
-- :}
511-
-- "{\"test_number\":1,\"test_newtype\":2,\"test_string\":\"s\",\"test_is_string\":\"t\",\"test_list\":[1,2,3],\"test_is_list\":[4,5,6],\"test_monoid\":[7,8,9]}"
500+
-- >>> encode $ StrippedJSON @'[] @'[ FieldLabelModifier CamelToSnake ] recordTest
501+
-- "{\"test_bool\":true,\"test_number\":1,\"test_newtype\":2,\"test_string\":\"s\",\"test_is_string\":\"t\",\"test_list\":[1,2,3],\"test_is_list\":[4,5,6],\"test_monoid\":\"GT\",\"test_value\":3.14}"

0 commit comments

Comments
 (0)