Skip to content

Instantly share code, notes, and snippets.

@sjoerdvisscher
Created April 7, 2021 20:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sjoerdvisscher/c01096714b006a27fa28542b8cd2ef85 to your computer and use it in GitHub Desktop.
Save sjoerdvisscher/c01096714b006a27fa28542b8cd2ef85 to your computer and use it in GitHub Desktop.
SameRepAs from the Deriving via paper https://www.kosmikus.org/DerivingVia/deriving-via-paper.pdf
{-# LANGUAGE DerivingStrategies, DerivingVia, TypeOperators, DataKinds,
DeriveGeneric #-}
module Rec where
import SameRepAs
import GHC.Generics ( Generic )
import qualified Data.Monoid as M
data Rec1 = Rec1 {a :: Bool, b :: Int}
deriving stock Generic
deriving (Semigroup, Monoid) via Rec1 `SameRepAs` ( M.Any, M.Sum Int )
data Rec2 = Rec2 {c :: Int, d :: Bool, e :: String}
deriving stock Generic
deriving (Semigroup, Monoid) via Rec2 `SameRepAs` ( M.Product Int, M.All, String )
{-# LANGUAGE ScopedTypeVariables, TypeApplications, TypeOperators,
FlexibleContexts, ConstraintKinds #-}
module SameRepAs where
import GHC.Generics ( Generic(..) )
import Data.Coerce
newtype SameRepAs a b = SameRepAs a
type HasSameRepAs a b = ( Generic a, Generic b, Coercible (Rep a ()) (Rep b ()) )
coerceViaRep :: forall a b. a `HasSameRepAs` b => a -> b
coerceViaRep = to . (coerce :: Rep a () -> Rep b ()) . from
instance ( a `HasSameRepAs` b, Semigroup b ) => Semigroup (a `SameRepAs` b) where
SameRepAs l <> SameRepAs r = SameRepAs $ coerceViaRep @b (coerceViaRep l <> coerceViaRep r)
instance ( a `HasSameRepAs` b, Monoid b ) => Monoid (a `SameRepAs` b) where
mempty = SameRepAs $ coerceViaRep @b mempty
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment