這使用GHC.Generics
提供showsPrecDefault
,它可以是很容易用來定義一個Show
實例。
data Person a = Person { name :: a, age :: Int } deriving Generic
instance Show a => Show (Person a) where showsPrec = showsPrecDefault
>>> Person "Alihuseyn" 20
Person "Alihuseyn" 20
showsPrecDefault
的定義如下。
{-# LANGUAGE
DeriveGeneric
, FlexibleContexts
, FlexibleInstances
, KindSignatures
, TypeOperators
, TypeSynonymInstances #-}
import GHC.Generics
class GShow f where
gshowsPrec :: Int -> f a -> ShowS
instance GShow U1 where
gshowsPrec _ U1 = id
instance Show c => GShow (Rec0 c) where
gshowsPrec p = showsPrec p . unK1
instance GShow f => GShow (D1 d f) where
gshowsPrec p = gshowsPrec p . unM1
instance Constructor c => GShow (C1 c U1) where
gshowsPrec _ [email protected](M1 U1) = showParen (isInfix c) (showString (conName c))
instance (Constructor c, GShow (M1 i c f)) => GShow (C1 c (M1 i c f)) where
gshowsPrec = gshowsPrec'
instance (Constructor c, GShow (f :+: g)) => GShow (C1 c (f :+: g)) where
gshowsPrec = gshowsPrec'
instance (Constructor c, GShow (f :*: g)) => GShow (C1 c (f :*: g)) where
gshowsPrec = gshowsPrec'
gshowsPrec' :: (Constructor c, GShow f) => Int -> C1 c f p -> ShowS
gshowsPrec' p [email protected](M1 f) =
showParen (p > 10) $
showParen (isInfix c) (showString (conName c)) .
showChar ' ' .
gshowsPrec 11 f
isInfix :: Constructor c => t c (f :: * -> *) a -> Bool
isInfix c = case conFixity c of
Infix _ _ -> True
_ -> False
instance GShow f => GShow (S1 s f) where
gshowsPrec p = gshowsPrec p . unM1
instance (GShow a, GShow b) => GShow (a :+: b) where
gshowsPrec p (L1 a) = gshowsPrec p a
gshowsPrec p (R1 b) = gshowsPrec p b
instance (GShow a, GShow b) => GShow (a :*: b) where
gshowsPrec p (a :*: b) =
gshowsPrec (p + 1) a .
showChar ' ' .
gshowsPrec (p + 1) b
showsPrecDefault :: (Generic a, GShow (Rep a)) => Int -> a -> ShowS
showsPrecDefault p = gshowsPrec p . from
那就不要導出'Show'實例,但自己編寫。如果您使用帶標記的字段來定義類型,則派生的'Show'實例將包含大括號和字段名稱。 – 2013-04-10 18:38:59