{-# language GADTs, TypeFamilies, ConstraintKinds, TypeOperators, FlexibleContexts, ScopedTypeVariables, DeriveGeneric #-} module Generics.Simplistic.Derive.Show where import Data.Functor.Identity import Generics.Simplistic import GHC.Generics -- An example data MyList a = MyNil | MyCons { hd :: a, tl :: MyList a } deriving Generic myListValue :: MyList Integer myListValue = MyCons 1 (MyCons 2 (MyCons 3 MyNil)) instance Show a => Show (MyList a) where show = gshow -- Translated from `generic-deriving` -- https://github.com/dreixel/generic-deriving/blob/master/src/Generics/Deriving/Show.hs appPrec :: Int appPrec = 2 data Type = Rec | Tup | Pref | Inf String gshow :: (GenericSy t, OnLeaves Show (Rep t)) => t -> String gshow v = gshowsPrec Pref 0 v "" gshowsPrec :: (GenericSy t, OnLeaves Show (Rep t)) => Type -> Int -> t -> ShowS gshowsPrec t n v = gshowsPrec' t n (fromS v) gshowsPrec' :: (OnLeaves Show f) => Type -> Int -> SRep Identity f -> ShowS -- "Simple" cases gshowsPrec' _ _ S_U1 = id gshowsPrec' t n (S_L1 x) = gshowsPrec' t n x gshowsPrec' t n (S_R1 x) = gshowsPrec' t n x gshowsPrec' _ n (S_K1 x) = showsPrec n x gshowsPrec' t n (S_ST x) = gshowsPrec' t n x -- The complex case of tuples gshowsPrec' t@Rec n (a :**: b) = gshowsPrec' t n a . showString ", " . gshowsPrec' t n b gshowsPrec' t@(Inf s) n (a :**: b) = gshowsPrec' t n a . showString s . gshowsPrec' t n b gshowsPrec' t@Tup n (a :**: b) = gshowsPrec' t n a . showChar ',' . gshowsPrec' t n b gshowsPrec' t@Pref n (a :**: b) = gshowsPrec' t (n+1) a . showChar ' ' . gshowsPrec' t (n+1) b -- The case of metadata gshowsPrec' t n (S_M1 (SM_C :: SMeta i c) (x :: SRep Identity f)) = case fixity of Prefix -> showParen (n > appPrec && not (isNullary x)) ( showString (conName c) . if (isNullary x) then id else showChar ' ' . showBraces t (gshowsPrec' t appPrec x)) Infix _ m -> showParen (n > m) (showBraces t (gshowsPrec' t m x)) where c :: M1 C c f () = undefined fixity = conFixity c t = if (conIsRecord c) then Rec else case (conIsTuple c) of True -> Tup False -> case fixity of Prefix -> Pref Infix _ _ -> Inf (show (conName c)) showBraces :: Type -> ShowS -> ShowS showBraces Rec p = showChar '{' . p . showChar '}' showBraces Tup p = showChar '(' . p . showChar ')' showBraces Pref p = p showBraces (Inf _) p = p conIsTuple :: C1 c f p -> Bool conIsTuple y = tupleName (conName y) where tupleName ('(':',':_) = True tupleName _ = False gshowsPrec' t n (S_M1 (SM_S :: SMeta i c) (x :: SRep Identity f)) | selName s == "" = --showParen (n > appPrec) (gshowsPrec' t n x) | otherwise = showString (selName s) . showString " = " . gshowsPrec' t 0 x where s :: M1 S c f () = undefined gshowsPrec' t n (S_M1 _ x) = gshowsPrec' t n x isNullary :: SRep Identity a -> Bool isNullary S_U1 = True isNullary (S_L1 x) = error "unnecessary case" isNullary (S_R1 x) = error "unnecessary case" isNullary (x :**: y) = False isNullary (S_K1 x) = False isNullary (S_M1 t x) = case t of SM_S -> isNullary x _ -> error "unnecessary case" isNullary (S_ST x) = isNullary x