module Glaze where
import Control.Lens
import Data.Proxy
data Glaze a r = Glaze
{ glazeRenderedMeta :: r
, glazeValueRenderer :: a -> r
} deriving Functor
class HasRenderedMeta s a | s -> a where
renderedMeta :: Lens' s a
instance HasRenderedMeta (Glaze a r) r where
renderedMeta f (Glaze x1 x2)
= fmap (\y1 -> Glaze y1 x2) (f x1)
class HasValueRenderer s a | s -> a where
valueRenderer :: Lens' s a
instance HasValueRenderer (Glaze a r) (a -> r) where
valueRenderer f (Glaze x1 x2)
= fmap (\y1 -> Glaze x1 y1) (f x2)
instance Applicative (Glaze a) where
pure a = Glaze a (const a)
x <*> y = Glaze
((x ^. renderedMeta) (y ^. renderedMeta))
(\a -> (x ^. valueRenderer) a ((y ^. valueRenderer) a))
renderWith :: (r -> r -> b) -> Glaze a r -> a -> b
renderWith mainWrapper rdr a =
mainWrapper (rdr ^. renderedMeta) ((rdr ^. valueRenderer) a)
glazeA ::
(Traversable t, Applicative m) =>
(wrapper -> meta -> t rs -> r) -> m wrapper -> m meta -> t (m rs) -> m r
glazeA f wrapper meta rs = f <$> wrapper <*> meta <*> sequenceA rs
glazeList :: ([row] -> r, [field] -> row, [field] -> row)
-> r
-> [Glaze a field]
-> Glaze [a] r
glazeList (mainWrapper, headerRowWrapper, valueRowWrapper) meta rs =
Glaze meta glazeList'
where
rs' = sequenceA rs
glazeList' as =
mainWrapper $
headerRowWrapper (rs' ^. renderedMeta) :
(valueRowWrapper . view valueRenderer rs' <$> as)
glazeListA ::
Applicative f =>
f ([row] -> r, [field] -> row, [field] -> row)
-> f r -> [f (Glaze a field)] -> f (Glaze [a] r)
glazeListA = glazeA glazeList
glazeFields :: ([(b, b)] -> r) -> r -> [Glaze a b] -> Glaze a r
glazeFields wrapper meta rs =
Glaze meta (\a -> wrapper $ (\r -> (r ^. renderedMeta, (r ^. valueRenderer) a)) <$> rs)
glazeFieldsA ::
Applicative f =>
f ([(b, b)] -> r) -> f r -> [f (Glaze a b)] -> f (Glaze a r)
glazeFieldsA = glazeA glazeFields
reglaze :: (Proxy a -> Glaze a r) -> Getter s a -> Glaze s r
reglaze f lns = Glaze
(rdr ^. renderedMeta)
(\s -> (rdr ^. valueRenderer) (s ^. lns))
where
rdr = f (Proxy :: Proxy a)
reglazeA :: Applicative f => (Proxy a -> f (Glaze a r)) -> Getter s a -> f (Glaze s r)
reglazeA f lns = (\rdr -> Glaze
(rdr ^. renderedMeta)
(\s -> (rdr ^. valueRenderer) (s ^. lns))) <$> f (Proxy :: Proxy a)