{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE PolyKinds #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} module Deriving.Show.Simple (showsPrecSimple, WrapSimple(..)) where import Data.Proxy import Data.List (intersperse) import GHC.Generics import GHC.TypeLits -- | Like 'showsPrec', but shows it as if their record fields are stripped showsPrecSimple :: (Generic a, GShowSimple (Rep a)) => Int -> a -> ShowS showsPrecSimple p a = case shows' (from a) of [x] -> x xs -> showParen (p > 10) $ foldr (.) id $ intersperse (showChar ' ') xs class GShowSimple f where shows' :: f x -> [ShowS] instance GShowSimple V1 where shows' _ = error "impossible" instance GShowSimple U1 where shows' _ = [] instance Show a => GShowSimple (K1 c a) where shows' (K1 a) = [showsPrec 11 a] instance (GShowSimple f, GShowSimple g) => GShowSimple (f :*: g) where shows' (f :*: g) = shows' f ++ shows' g instance (GShowSimple f, GShowSimple g) => GShowSimple (f :+: g) where shows' (L1 a) = shows' a shows' (R1 a) = shows' a instance (KnownSymbol name, GShowSimple f, c ~ 'MetaCons name fix rec) => GShowSimple (C1 c f) where shows' (M1 a) = showString (symbolVal (Proxy :: Proxy name)) : shows' a instance (GShowSimple f) => GShowSimple (D1 meta f) where shows' (M1 a) = shows' a instance (GShowSimple f) => GShowSimple (S1 meta f) where shows' (M1 a) = shows' a -- | The 'Show' instance uses 'showsPrecSimple'. Useful in combination with DerivingVia newtype WrapSimple a = WrapSimple { unwrapSimple :: a } instance (Generic a, GShowSimple (Rep a)) => Show (WrapSimple a) where showsPrec d = showsPrecSimple d . unwrapSimple