module Generics.MultiRec.Show where
import Generics.MultiRec.Base
import Generics.MultiRec.HFunctor
import Generics.MultiRec.FoldK
import qualified Prelude as P
import Prelude hiding (show, showsPrec)
import Data.Traversable (Traversable(..))
class HFunctor phi f => HShow phi f where
hShowsPrecAlg :: Algebra' phi f [Int -> ShowS]
instance El phi xi => HShow phi (I xi) where
hShowsPrecAlg _ (I (K0 x)) = x
instance Show a => HShow phi (K a) where
hShowsPrecAlg _ (K x) = [\ n -> P.showsPrec n x]
instance HShow phi U where
hShowsPrecAlg _ U = []
instance (HShow phi f, HShow phi g) => HShow phi (f :+: g) where
hShowsPrecAlg ix (L x) = hShowsPrecAlg ix x
hShowsPrecAlg ix (R y) = hShowsPrecAlg ix y
instance (HShow phi f, HShow phi g) => HShow phi (f :*: g) where
hShowsPrecAlg ix (x :*: y) = hShowsPrecAlg ix x ++ hShowsPrecAlg ix y
instance HShow phi f => HShow phi (f :>: ix) where
hShowsPrecAlg ix (Tag x) = hShowsPrecAlg ix x
instance (Show1 f, Traversable f, HShow phi g) => HShow phi (f :.: g) where
hShowsPrecAlg ix (D x) = [show1 (fmap (hShowsPrecAlg ix) x)]
instance (Constructor c, HShow phi f) => HShow phi (C c f) where
hShowsPrecAlg ix cx@(C x) =
case conFixity cx of
Prefix -> [\ n -> showParen (not (null fields) && n > 10)
(spaces ((conName cx ++) : map ($ 11) fields))]
Infix a p -> [\ n -> showParen (n > p)
(spaces (head fields p : (conName cx ++) : map ($ p) (tail fields)))]
where
fields = hShowsPrecAlg ix x
class Show1 f where
show1 :: f [Int -> ShowS] -> Int -> ShowS
instance Show1 Maybe where
show1 Nothing _ = ("Nothing" ++)
show1 (Just x) n = showParen (n > 10) (spaces (("Just" ++) : map ($ 11) x))
instance Show1 [] where
show1 [] _ = ("[]" ++)
show1 xs _ = ('[':) . commas (map ($ 0) (concat xs)) . (']':)
showsPrec :: (Fam phi, HShow phi (PF phi)) => phi ix -> Int -> ix -> ShowS
showsPrec p n x = spaces (map ($ n) (fold hShowsPrecAlg p x))
show :: (Fam phi, HShow phi (PF phi)) => phi ix -> ix -> String
show ix x = showsPrec ix 0 x ""
spaces :: [ShowS] -> ShowS
spaces = intersperse " "
commas :: [ShowS] -> ShowS
commas = intersperse ", "
intersperse :: String -> [ShowS] -> ShowS
intersperse s [] = id
intersperse s [x] = x
intersperse s (x:xs) = x . (s ++) . spaces xs