{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE EmptyCase #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Data.Singletons.Prelude.Show (
PShow(..), SShow(..), SymbolS, SChar, show_,
Shows, sShows,
ShowListWith, sShowListWith,
ShowChar, sShowChar,
ShowString, sShowString,
ShowParen, sShowParen,
ShowSpace, sShowSpace,
ShowCommaSpace, sShowCommaSpace,
AppPrec, sAppPrec,
AppPrec1, sAppPrec1,
ShowsPrecSym0, ShowsPrecSym1, ShowsPrecSym2, ShowsPrecSym3,
Show_Sym0, Show_Sym1,
ShowListSym0, ShowListSym1, ShowListSym2,
ShowsSym0, ShowsSym1, ShowsSym2,
ShowListWithSym0, ShowListWithSym1, ShowListWithSym2, ShowListWithSym3,
ShowCharSym0, ShowCharSym1, ShowCharSym2,
ShowStringSym0, ShowStringSym1, ShowStringSym2,
ShowParenSym0, ShowParenSym1, ShowParenSym2,
ShowSpaceSym0, ShowSpaceSym1,
ShowCommaSpaceSym0, ShowCommaSpaceSym1,
AppPrecSym0, AppPrec1Sym0
) where
import Data.List.NonEmpty (NonEmpty)
import Data.Ord (Down)
import Data.Proxy
import Data.Singletons.Internal
import Data.Singletons.Prelude.Base
import Data.Singletons.Prelude.Instances
import Data.Singletons.Prelude.List.Internal
import Data.Singletons.Prelude.Ord
import Data.Singletons.Prelude.Semigroup.Internal
import Data.Singletons.Promote
import Data.Singletons.Single
import Data.Singletons.TypeLits
import qualified Data.Text as T
import Data.Void
import GHC.TypeLits
import qualified Prelude as P
import Prelude hiding (Show(..))
import Unsafe.Coerce (unsafeCoerce)
type SymbolS = Symbol -> Symbol
type SChar = Symbol
$(singletonsOnly [d|
class Show a where
showsPrec :: Nat -> a -> SymbolS
show_ :: a -> Symbol
showList :: [a] -> SymbolS
showsPrec _ x s = show_ x <> s
show_ x = shows x ""
showList ls s = showListWith shows ls s
shows :: Show a => a -> SymbolS
shows s = showsPrec 0 s
showListWith :: (a -> SymbolS) -> [a] -> SymbolS
showListWith _ [] s = "[]" <> s
showListWith showx (x:xs) s = "[" <> showx x (showl xs)
where
showl [] = "]" <> s
showl (y:ys) = "," <> showx y (showl ys)
showChar :: SChar -> SymbolS
showChar = (<>)
showString :: Symbol -> SymbolS
showString = (<>)
showParen :: Bool -> SymbolS -> SymbolS
showParen b p = if b then showChar "(" . p . showChar ")" else p
showSpace :: SymbolS
showSpace = \xs -> " " <> xs
showCommaSpace :: SymbolS
showCommaSpace = showString ", "
appPrec, appPrec1 :: Nat
appPrec = 10
appPrec1 = 11
instance Show a => Show [a] where
showsPrec _ = showList
instance Show Symbol where
showsPrec _ = showString
show_tuple :: [SymbolS] -> SymbolS
show_tuple ss = showChar "("
. foldr1 (\s r -> s . showChar "," . r) ss
. showChar ")"
instance (Show a, Show b) => Show (a,b) where
showsPrec _ (a,b) s = show_tuple [shows a, shows b] s
instance (Show a, Show b, Show c) => Show (a, b, c) where
showsPrec _ (a,b,c) s = show_tuple [shows a, shows b, shows c] s
instance (Show a, Show b, Show c, Show d) => Show (a, b, c, d) where
showsPrec _ (a,b,c,d) s = show_tuple [shows a, shows b, shows c, shows d] s
instance (Show a, Show b, Show c, Show d, Show e) => Show (a, b, c, d, e) where
showsPrec _ (a,b,c,d,e) s = show_tuple [shows a, shows b, shows c, shows d, shows e] s
instance (Show a, Show b, Show c, Show d, Show e, Show f) => Show (a,b,c,d,e,f) where
showsPrec _ (a,b,c,d,e,f) s = show_tuple [shows a, shows b, shows c, shows d, shows e, shows f] s
instance (Show a, Show b, Show c, Show d, Show e, Show f, Show g)
=> Show (a,b,c,d,e,f,g) where
showsPrec _ (a,b,c,d,e,f,g) s
= show_tuple [shows a, shows b, shows c, shows d, shows e, shows f, shows g] s
deriving instance Show a => Show (Down a)
|])
$(promoteOnly [d|
showsNat :: Nat -> SymbolS
showsNat 0 = showChar "0"
showsNat 1 = showChar "1"
showsNat 2 = showChar "2"
showsNat 3 = showChar "3"
showsNat 4 = showChar "4"
showsNat 5 = showChar "5"
showsNat 6 = showChar "6"
showsNat 7 = showChar "7"
showsNat 8 = showChar "8"
showsNat 9 = showChar "9"
showsNat n = showsNat (n `div` 10) . showsNat (n `mod` 10)
|])
instance PShow Nat where
type ShowsPrec _ n x = ShowsNat n x
instance SShow Nat where
sShowsPrec _ sn sx =
let n = fromSing sn
x = fromSing sx
ex = someSymbolVal (P.show n ++ T.unpack x)
in
case ex of
SomeSymbol (_ :: Proxy s) -> unsafeCoerce (SSym :: Sing s)
show_ :: P.Show a => a -> String
show_ = P.show
$(singShowInstances [ ''(), ''Maybe, ''Either, ''NonEmpty, ''Bool,
''Ordering, ''Void ])