Skip to content

Commit 34264ac

Browse files
committed
Binary instance for Generically.
1 parent 4eb7468 commit 34264ac

File tree

4 files changed

+69
-19
lines changed

4 files changed

+69
-19
lines changed

README.md

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
The ``binary`` package provides Data.Binary, containing the Binary class,
88
and associated methods, for serialising values to and from lazy
9-
ByteStrings.
9+
ByteStrings.
1010
A key feature of ``binary`` is that the interface is both pure, and efficient.
1111
The ``binary`` package is portable to GHC and Hugs.
1212

@@ -54,23 +54,41 @@ the ``Get`` and ``Put`` monads.
5454

5555
More information in the haddock documentation.
5656

57-
## Deriving binary instances using GHC's Generic ##
57+
## Deriving binary instances, ``Generically`` ##
5858

59-
Beginning with GHC 7.2, it is possible to use binary serialization without
60-
writing any instance boilerplate code.
59+
Beginning with GHC 9.4 it is possible to derive binary serialization
60+
using the ``Generically`` newtype.
61+
62+
This is achieved by deriving an instance of ``Generic`` and then
63+
deriving the appropriate ``Binary T`` instance via ``Generically T``.
6164

6265
```haskell
63-
{-# LANGUAGE DeriveGeneric #-}
66+
{-# LANGUAGE DeriveAnyClass #-}
67+
{-# LANGUAGE DeriveGeneric #-}
68+
{-# LANGUAGE DerivingStrategies #-}
69+
{-# LANGUAGE DerivingVia #-}
6470

6571
import Data.Binary
66-
import GHC.Generics (Generic)
72+
import GHC.Generics (Generic, Generically(..))
73+
74+
data Foo = Foo
75+
deriving stock Generic
76+
deriving Binary via Generically Foo
77+
```
6778

68-
data Foo = Foo deriving (Generic)
79+
Beginning with GHC 7.2 this generic definition has been a part of the
80+
``Binary`` typeclass. This could also be derived using the
81+
``anyclass`` strategy:
6982

70-
-- GHC will automatically fill out the instance
71-
instance Binary Foo
83+
```haskell
84+
data Foo = Foo
85+
deriving stock Generic
86+
deriving anyclass Binary
7287
```
7388

89+
Which means the same as an empty class declaration: ``instance
90+
Binary Foo``.
91+
7492
## Contributors ##
7593

7694
* Lennart Kolmodin

changelog.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ binary
44
binary-0.8.9.0
55
--------------
66

7+
- Add binary instance for 'GHC.Generics.Generically'. `Binary T` can
8+
be derived via `Generically T` for a suitable generic type `T`.
9+
10+
binary-0.8.9.0
11+
--------------
12+
713
- Compatibility with GHC 9.2
814
- Drop instances for deprecated `Data.Semigroup.Option`
915

src/Data/Binary.hs

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -230,19 +230,32 @@ decodeFileOrFail f =
230230
------------------------------------------------------------------------
231231
-- $generics
232232
--
233-
-- Beginning with GHC 7.2, it is possible to use binary serialization
234-
-- without writing any instance boilerplate code.
233+
-- Beginning with GHC 9.4 it is possible to derive binary
234+
-- serialization using the 'GHC.Generics.Generically' newtype.
235235
--
236-
-- > {-# LANGUAGE DeriveGeneric #-}
236+
-- This is achieved by deriving an instance of 'GHC.Generics.Generic'
237+
-- and then deriving the appropriate @'Binary' T@ instance via
238+
-- @Generically T@.
239+
--
240+
-- > {-# LANGUAGE DeriveAnyClass #-}
241+
-- > {-# LANGUAGE DeriveGeneric #-}
242+
-- > {-# LANGUAGE DerivingStrategies #-}
243+
-- > {-# LANGUAGE DerivingVia #-}
237244
-- >
238245
-- > import Data.Binary
239-
-- > import GHC.Generics (Generic)
246+
-- > import GHC.Generics (Generic, Generically(..))
240247
-- >
241248
-- > data Foo = Foo
242-
-- > deriving (Generic)
243-
-- >
244-
-- > -- GHC will automatically fill out the instance
245-
-- > instance Binary Foo
249+
-- > deriving stock Generic
250+
-- > deriving Binary via Generically Foo
246251
--
247-
-- This mechanism makes use of GHC's efficient built-in generics
248-
-- support.
252+
-- Beginning with GHC 7.2 this generic definition has been a part of
253+
-- the 'Binary' typeclass. This could also be derived using the
254+
-- @anyclass@ strategy:
255+
--
256+
-- > data Foo = Foo
257+
-- > deriving stock Generic
258+
-- > deriving anyclass Binary
259+
--
260+
-- Which means the same as an empty class declaration: @instance
261+
-- Binary Foo@.

src/Data/Binary/Class.hs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
#define HAS_TYPELITS_CHAR
1414
#endif
1515

16+
#if MIN_VERSION_base(4,17,0)
17+
#define HAS_GENERICALLY
18+
#endif
19+
1620
#if MIN_VERSION_base(4,8,0)
1721
#define HAS_NATURAL
1822
#define HAS_VOID
@@ -175,6 +179,15 @@ class Binary t where
175179
defaultPutList :: Binary a => [a] -> Put
176180
defaultPutList xs = put (length xs) <> mapM_ put xs
177181

182+
#ifdef HAS_GENERICALLY
183+
instance (Generic a, GBinaryPut (Rep a), GBinaryGet (Rep a)) => Binary (Generically a) where
184+
put :: Generically a -> Put
185+
put (Generically a) = gput (from a)
186+
187+
get :: Get (Generically a)
188+
get = Generically . to <$> gget
189+
#endif
190+
178191
------------------------------------------------------------------------
179192
-- Simple instances
180193

0 commit comments

Comments
 (0)