{-# LANGUAGE AllowAmbiguousTypes #-}
module TypeLevelShow.Doc where
import GHC.TypeLits qualified as TE
import GHC.TypeLits ( Symbol, KnownSymbol, symbolVal' )
import GHC.Exts ( proxy# )
data Doc s
= Text s
| Doc s :<>: Doc s
| Doc s :$$: Doc s
deriving stock Int -> Doc s -> ShowS
[Doc s] -> ShowS
Doc s -> String
(Int -> Doc s -> ShowS)
-> (Doc s -> String) -> ([Doc s] -> ShowS) -> Show (Doc s)
forall s. Show s => Int -> Doc s -> ShowS
forall s. Show s => [Doc s] -> ShowS
forall s. Show s => Doc s -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall s. Show s => Int -> Doc s -> ShowS
showsPrec :: Int -> Doc s -> ShowS
$cshow :: forall s. Show s => Doc s -> String
show :: Doc s -> String
$cshowList :: forall s. Show s => [Doc s] -> ShowS
showList :: [Doc s] -> ShowS
Show
type PDoc = Doc Symbol
type RenderDoc :: PDoc -> TE.ErrorMessage
type family RenderDoc doc where
RenderDoc (Text s) = TE.Text s
RenderDoc (l :<>: r) = RenderDoc l TE.:<>: RenderDoc r
RenderDoc (l :$$: r) = RenderDoc l TE.:$$: RenderDoc r
class ReifyDoc (doc :: PDoc) where
reifyDoc :: Doc String
instance KnownSymbol s => ReifyDoc (Text s) where
reifyDoc :: Doc String
reifyDoc = String -> Doc String
forall s. s -> Doc s
Text (String -> Doc String) -> String -> Doc String
forall a b. (a -> b) -> a -> b
$ Proxy# s -> String
forall (n :: Symbol). KnownSymbol n => Proxy# n -> String
symbolVal' (forall {k} (a :: k). Proxy# a
forall (a :: Symbol). Proxy# a
proxy# @s)
instance (ReifyDoc l, ReifyDoc r) => ReifyDoc (l :<>: r) where
reifyDoc :: Doc String
reifyDoc = forall (doc :: PDoc). ReifyDoc doc => Doc String
reifyDoc @l Doc String -> Doc String -> Doc String
forall s. Doc s -> Doc s -> Doc s
:<>: forall (doc :: PDoc). ReifyDoc doc => Doc String
reifyDoc @r
instance (ReifyDoc l, ReifyDoc r) => ReifyDoc (l :$$: r) where
reifyDoc :: Doc String
reifyDoc = forall (doc :: PDoc). ReifyDoc doc => Doc String
reifyDoc @l Doc String -> Doc String -> Doc String
forall s. Doc s -> Doc s -> Doc s
:$$: forall (doc :: PDoc). ReifyDoc doc => Doc String
reifyDoc @r