hakyll
hakyll copied to clipboard
Add boolFieldM which allows using the Compiler monad
This commits adds the helper boolFieldM. In contrast to boolField it allows using the Compiler monad in the passed function. boolField is also redefined in terms of boolFieldM. Closes #564
Any news on this PR?
Just curious, what are you using this for?
Also what would you think of a maybeField :: String -> (Item a -> Compiler (Maybe String)) -> Context a
Just curious, what are you using this for?
I'm building a multi-level navigation menu by iterating over Item
s. Links in the navigation that link to the current site or to sites hierarchically above the current site should be rendered in a special way. I currently do this by giving each of the menu Item
s a field that tests for the conditions mentioned above by comparing parts of the Item
's Identifier
with the current page's Identifier
. The latter is obtained with getUnderlying, which is what I need the Compiler
for.
Also what would you think of a
maybeField :: String -> (Item a -> Compiler (Maybe String)) -> Context a
Definitely looks like something that might be useful from time to time.
I'm fine merging this unless this conflicts with the progress on better error messages @bergus
No, doesn't really conflict with that (the collision is easy to resolve), however I'm not sold on the name boolFieldM
. We should get a clear naming convention for how to construct Context
s with functions that return strings, bools, lists (or Compiler
s for them) from items, from items+arguments or from nothing.
Also I'm currently experimenting with
class ContextFieldable a where -- a horrible name. Suggestions?
toContextField :: a -> Compiler ContextField
instance ContextFieldable ContextField where
toContextField = return
instance ContextFieldable a => ContextFieldable (Compiler a) where
toContextField = (>>= toContextField)
instance ContextFieldable [Char] where
toContextField = return . StringField
instance ContextFieldable Bool where
toContextField True = return EmptyField
toContextField False = compilerNoResult "false"
instance ContextFieldable a => ContextFieldable (Maybe a) where
toContextField = maybe (compilerNoResult "false") toContextField
--------------------------------------------------------------------------------
functionContext :: ContextFieldable c => String -> ([String] -> Item a -> c) -> Context a
functionContext key value = Context $ \k args item ->
if k == key
then mapError (("In field "++key):) $ toContextField $ value args item
else compilerNoResult $ "Tried field " ++ key
context :: ContextFieldable c => String -> (Item a -> c) -> Context a
context key = functionContext key . const
which would allow field = context
, boolField = context
, constField key = context key . const
, functionField = functionContext
, and also boolFieldM = context
- it's super-flexible. Maybe too flexible? If you want to consider this, I'm gonna file a separate pull request, superseding this one. Either is largely independent from the error messages PR though.
Oh yeah something like that would work as well. I would just call the typeclass ToContextField
.