-- | Most users of this library do not need this module. The functions -- here are used to build functions that apply a 'Colonnade' -- to a collection of values, building a table from them. Ultimately, -- a function that applies a @Colonnade Headed MyCell a@ -- to data will have roughly the following type: -- -- > myTableRenderer :: Foldable g => Colonnade Headed MyCell a -> g a -> MyContent -- -- In the companion packages @yesod-colonnade@ and -- @reflex-dom-colonnade@, functions with -- similar type signatures are readily available. -- These packages use the functions provided here -- in the implementations of their rendering functions. -- It is recommended that users who believe they may need -- this module look at the source of the companion packages -- to see an example of how this module\'s functions are used. -- Other backends are encouraged to use these functions -- to build monadic or monoidal content from a 'Colonnade'. -- -- The functions exported here take a 'Colonnade' and -- convert it to a fragment of content. The functions whose -- names start with @row@ take at least a @Colonnade f c a@ and an @a@ -- value to generate a row of content. The functions whose names -- start with @header@ need the @Colonnade f c a@ but not -- an @a@ value since a value is not needed to build a header. -- module Colonnade.Encode ( row , rowMonadic , rowMonadic_ , rowMonadicWith , rowMonoidal , header , headerMonadic , headerMonadic_ , headerMonadicGeneral , headerMonadicGeneral_ , headerMonoidalGeneral , bothMonadic_ ) where import Colonnade.Internal import Data.Vector (Vector) import Data.Foldable import qualified Data.Vector as Vector -- | Consider providing a variant the produces a list -- instead. It may allow more things to get inlined -- in to a loop. row :: (c1 -> c2) -> Colonnade f c1 a -> a -> Vector c2 row g (Colonnade v) a = flip Vector.map v $ \(OneColonnade _ encode) -> g (encode a) bothMonadic_ :: Monad m => Colonnade Headed content a -> (content -> content -> m b) -> a -> m () bothMonadic_ (Colonnade v) g a = forM_ v $ \(OneColonnade (Headed h) encode) -> g h (encode a) rowMonadic :: (Monad m, Monoid b) => Colonnade f content a -> (content -> m b) -> a -> m b rowMonadic (Colonnade v) g a = flip foldlMapM v $ \e -> g (oneColonnadeEncode e a) rowMonadic_ :: Monad m => Colonnade f content a -> (content -> m b) -> a -> m () rowMonadic_ (Colonnade v) g a = forM_ v $ \e -> g (oneColonnadeEncode e a) rowMonoidal :: Monoid m => Colonnade h c a -> (c -> m) -> a -> m rowMonoidal (Colonnade v) g a = foldMap (\e -> g (oneColonnadeEncode e a)) v rowMonadicWith :: (Monad m) => b -> (b -> b -> b) -> Colonnade f content a -> (content -> m b) -> a -> m b rowMonadicWith bempty bappend (Colonnade v) g a = foldlM (\bl e -> do br <- g (oneColonnadeEncode e a) return (bappend bl br) ) bempty v header :: (c1 -> c2) -> Colonnade Headed c1 a -> Vector c2 header g (Colonnade v) = Vector.map (g . getHeaded . oneColonnadeHead) v -- | This function is a helper for abusing 'Foldable' to optionally -- render a header. Its future is uncertain. headerMonadicGeneral :: (Monad m, Monoid b, Foldable h) => Colonnade h content a -> (content -> m b) -> m b headerMonadicGeneral (Colonnade v) g = id $ fmap (mconcat . Vector.toList) $ Vector.mapM (foldlMapM g . oneColonnadeHead) v headerMonadic :: (Monad m, Monoid b) => Colonnade Headed content a -> (content -> m b) -> m b headerMonadic (Colonnade v) g = fmap (mconcat . Vector.toList) $ Vector.mapM (g . getHeaded . oneColonnadeHead) v headerMonadicGeneral_ :: (Monad m, Foldable h) => Colonnade h content a -> (content -> m b) -> m () headerMonadicGeneral_ (Colonnade v) g = Vector.mapM_ (mapM_ g . oneColonnadeHead) v headerMonoidalGeneral :: (Monoid m, Foldable h) => Colonnade h c a -> (c -> m) -> m headerMonoidalGeneral (Colonnade v) g = foldMap (foldMap g . oneColonnadeHead) v headerMonadic_ :: (Monad m) => Colonnade Headed content a -> (content -> m b) -> m () headerMonadic_ (Colonnade v) g = Vector.mapM_ (g . getHeaded . oneColonnadeHead) v foldlMapM :: (Foldable t, Monoid b, Monad m) => (a -> m b) -> t a -> m b foldlMapM f = foldlM (\b a -> fmap (mappend b) (f a)) mempty