diff --git a/README.md b/README.md index e39348d..aa9e6f3 100644 --- a/README.md +++ b/README.md @@ -55,23 +55,41 @@ the ``Get`` and ``Put`` monads. More information in the haddock documentation. -## Deriving binary instances using GHC's Generic ## +## Deriving binary instances, ``Generically`` ## -Beginning with GHC 7.2, it is possible to use binary serialization without -writing any instance boilerplate code. +Beginning with GHC 9.4 it is possible to derive binary serialization +using the ``Generically`` newtype. + +This is achieved by deriving an instance of ``Generic`` and then +deriving the appropriate ``Binary T`` instance via ``Generically T``. ```haskell -{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE DeriveAnyClass #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE DerivingStrategies #-} +{-# LANGUAGE DerivingVia #-} import Data.Binary -import GHC.Generics (Generic) +import GHC.Generics (Generic, Generically(..)) + +data Foo = Foo + deriving stock Generic + deriving Binary via Generically Foo +``` -data Foo = Foo deriving (Generic) +Beginning with GHC 7.2 this generic definition has been a part of the +``Binary`` typeclass. This could also be derived using the +``anyclass`` strategy: --- GHC will automatically fill out the instance -instance Binary Foo +```haskell +data Foo = Foo + deriving stock Generic + deriving anyclass Binary ``` +Which means the same as an empty class declaration: ``instance +Binary Foo``. + ## Contributors ## * Lennart Kolmodin diff --git a/changelog.md b/changelog.md index 44cf48b..6703e00 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,13 @@ binary ====== + +binary-0.8.9.2 +-------------- + +- Add binary instance for `GHC.Generics.Generically`. `Binary T` can + be derived via `Generically T` for a suitable generic type `T`. + binary-0.8.9.1 -------------- diff --git a/src/Data/Binary.hs b/src/Data/Binary.hs index 07970a3..4e964f6 100644 --- a/src/Data/Binary.hs +++ b/src/Data/Binary.hs @@ -230,19 +230,32 @@ decodeFileOrFail f = ------------------------------------------------------------------------ -- $generics -- --- Beginning with GHC 7.2, it is possible to use binary serialization --- without writing any instance boilerplate code. +-- Beginning with GHC 9.4 it is possible to derive binary +-- serialization using the 'GHC.Generics.Generically' newtype. -- --- > {-# LANGUAGE DeriveGeneric #-} +-- This is achieved by deriving an instance of 'GHC.Generics.Generic' +-- and then deriving the appropriate @'Binary' T@ instance via +-- @Generically T@. +-- +-- > {-# LANGUAGE DeriveAnyClass #-} +-- > {-# LANGUAGE DeriveGeneric #-} +-- > {-# LANGUAGE DerivingStrategies #-} +-- > {-# LANGUAGE DerivingVia #-} -- > -- > import Data.Binary --- > import GHC.Generics (Generic) +-- > import GHC.Generics (Generic, Generically(..)) -- > -- > data Foo = Foo --- > deriving (Generic) --- > --- > -- GHC will automatically fill out the instance --- > instance Binary Foo +-- > deriving stock Generic +-- > deriving Binary via Generically Foo -- --- This mechanism makes use of GHC's efficient built-in generics --- support. +-- Beginning with GHC 7.2 this generic definition has been a part of +-- the 'Binary' typeclass. This could also be derived using the +-- @anyclass@ strategy: +-- +-- > data Foo = Foo +-- > deriving stock Generic +-- > deriving anyclass Binary +-- +-- Which means the same as an empty class declaration: @instance +-- Binary Foo@. diff --git a/src/Data/Binary/Class.hs b/src/Data/Binary/Class.hs index bc4bc6b..428742e 100644 --- a/src/Data/Binary/Class.hs +++ b/src/Data/Binary/Class.hs @@ -13,6 +13,10 @@ #define HAS_TYPELITS_CHAR #endif +#if MIN_VERSION_base(4,17,0) +#define HAS_GENERICALLY +#endif + #if MIN_VERSION_base(4,8,0) #define HAS_NATURAL #define HAS_VOID @@ -175,6 +179,15 @@ class Binary t where defaultPutList :: Binary a => [a] -> Put defaultPutList xs = put (length xs) <> mapM_ put xs +#ifdef HAS_GENERICALLY +instance (Generic a, GBinaryPut (Rep a), GBinaryGet (Rep a)) => Binary (Generically a) where + put :: Generically a -> Put + put (Generically a) = gput (from a) + + get :: Get (Generically a) + get = Generically . to <$> gget +#endif + ------------------------------------------------------------------------ -- Simple instances