Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CONTRIBUTORS
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ Carl Howells <chowells79@gmail.com>
Edward Kmett
Will Langstroth <will@langstroth.com>
Shane O'Brien <shane@duairc.com>
Kari Pahula <kaol@iki.fi>
James Sanders <jimmyjazz14@gmail.com>
Mark Wright <gienah@gentoo.org>
2 changes: 2 additions & 0 deletions src/Heist/Compiled.hs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ module Heist.Compiled
, pureSplice

, deferMany
, deferManyElse
, defer
, deferEither
, deferMap
, mayDeferMap
, bindLater
Expand Down
41 changes: 39 additions & 2 deletions src/Heist/Compiled/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import qualified Text.XmlHtml.HTML.Meta as X
------------------------------------------------------------------------------
#if !MIN_VERSION_base(4,8,0)
import Data.Foldable (Foldable)
import Data.Monoid
#endif
import qualified Data.Foldable as Foldable
------------------------------------------------------------------------------
Expand Down Expand Up @@ -749,12 +750,31 @@ deferMany :: (Foldable f, Monad n)
=> (RuntimeSplice n a -> Splice n)
-> RuntimeSplice n (f a)
-> Splice n
deferMany f getItems = do
deferMany = deferManyElse $ return mempty


------------------------------------------------------------------------------
-- | A version of 'deferMany' which has a default splice to run in the case
-- when there are no elements in the given list.
deferManyElse :: (Foldable f, Monad n)
=> Splice n
-> (RuntimeSplice n a -> Splice n)
-> RuntimeSplice n (f a)
-> Splice n
deferManyElse def f getItems = do
promise <- newEmptyPromise
chunks <- f $ getPromise promise
defaultChunk <- def
return $ yieldRuntime $ do
items <- getItems
foldMapM (\item -> putPromise promise item >> codeGen chunks) items
if nullGeneric items
then codeGen defaultChunk
else foldMapM (\item -> putPromise promise item >>
codeGen chunks) items
where
-- Use this instead of null for compatibility with pre 4.8 base
nullGeneric = foldrGeneric (\_ _ -> False) True
foldrGeneric f' z t = appEndo (foldMap (Endo . f') t) z


------------------------------------------------------------------------------
Expand All @@ -773,6 +793,23 @@ defer pf n = do
return $ action `mappend` res


------------------------------------------------------------------------------
-- | Much like 'either', takes a runtime computation and branches to the
-- respective splice depending on the runtime value.
deferEither :: Monad n
=> (RuntimeSplice n a -> Splice n)
-> (RuntimeSplice n b -> Splice n)
-> RuntimeSplice n (Either a b) -> Splice n
deferEither pfa pfb n = do
pa <- newEmptyPromise
pb <- newEmptyPromise
failureChunk <- pfa $ getPromise pa
successChunk <- pfb $ getPromise pb
return $ yieldRuntime $ n >>= either
(\x -> putPromise pa x >> codeGen failureChunk)
(\x -> putPromise pb x >> codeGen successChunk)


------------------------------------------------------------------------------
-- | A version of defer which applies a function on the runtime value.
deferMap :: Monad n
Expand Down