{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE MonoLocalBinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE PolyKinds #-}
module Html.Reify where
import Html.Type.Internal
import Html.Convert
import Data.Proxy
import Data.Semigroup ((<>))
import Data.ByteString.Builder (Builder)
import GHC.Exts
type Document' a = R (T (ToList a) a)
type family Document a where Document a = Document' a
{-# INLINE renderBuilder #-}
renderBuilder :: Document a => a -> Builder
renderBuilder = unConv . render . (T :: a -> T (ToList a) a) . inline
class R a where
render :: a -> Converted
instance {-# INCOHERENT #-}
R (T '[] val) where
{-# INLINE render #-}
render _ = mempty
instance {-# INCOHERENT #-}
( Convert val
) => R (T '[ "" ] val) where
{-# INLINE render #-}
render (T x) = convert x
instance
( Convert b
, Convert (Proxy s)
) => R (T '[s] (a := b)) where
{-# INLINE render #-}
render (T (AT x)) = convert (Proxy @ s) <> convert x
instance {-# INCOHERENT #-}
( Convert val
, Convert (Proxy s)
) => R (T '[s] val) where
{-# INLINE render #-}
render (T x) = convert (Proxy @ s) <> convert x
instance {-# OVERLAPPING #-}
( Convert (Proxy s)
) => R (T '[s] String) where
{-# INLINE render #-}
render (T x) = convert (Proxy @ s) <> convert x
instance {-# OVERLAPPING #-}
( R (T xs val)
) => R (T ('List xs "") val) where
{-# INLINE render #-}
render (T t) = render (T t :: T xs val)
instance
( R (T xs val)
, Convert (Proxy x)
) => R (T ('List xs x) val) where
{-# INLINE render #-}
render (T t) = render (T t :: T xs val) <> convert (Proxy @ x)
instance
( R (T (Take (Length b) ps) b)
, R (T (Drop (Length b) ps) c)
) => R (T ps ((a :@: b) c)) where
{-# INLINE render #-}
render (T ~(WithAttributes b c))
= render (T b :: T (Take (Length b) ps) b)
<> render (T c :: T (Drop (Length b) ps) c)
instance
( R (T (Take (Length a) ps) a)
, R (T (Drop (Length a) ps) b)
) => R (T ps (a # b)) where
{-# INLINE render #-}
render (T ~(a :#: b))
= render (T a :: T (Take (Length a) ps) a)
<> render (T b :: T (Drop (Length a) ps) b)
instance
( R (T (ToList a) a)
, Convert (Proxy s)
) => R (T (s ': ss) [a]) where
{-# INLINE render #-}
render (T xs)
= convert (Proxy @ s)
<> foldMap (Converted . renderBuilder) xs
instance
( R (T (ToList a) a)
, Convert (Proxy s)
) => R (T (s ': ss) (Maybe a)) where
{-# INLINE render #-}
render (T mx)
= convert (Proxy @ s)
<> foldMap (Converted . renderBuilder) mx
instance
( R (T (ToList a) a)
, R (T (ToList b) b)
, Convert (Proxy s)
) => R (T (s ': ss) (Either a b)) where
{-# INLINE render #-}
render (T eab)
= convert (Proxy @ s)
<> either (Converted . renderBuilder) (Converted . renderBuilder) eab