úÎWùSá)      !"#$%&'( Safe-Inferred       None1234JK&Turn haskell values into JSON objects.‹This is the mechanism used by EDE to marshall data from Haskell to the templates. The rendering is then just about feeding the resulting ) to a compiled Template . Example: Çimport Text.EDE data User = User { name :: String, age :: Int } instance ToObject User where toObject user = fromPairs [ "name" .= name user , "age" .= age user ]¹However, you're not forced to write the instance yourself for such a type. Indeed, for any record type (i.e a datatype with a single constructor and with field selectors) you can let  GHC.Generics derive the  instance for you. Wdata User = User { name :: String, age :: Int } deriving Generic instance ToObject User>This will generate an equivalent instance to the previous one.Turn values of type a into JSON )s. -- Reminder: type Object = * + ,   None(=JKM ¯Helper class to reify a type-level list of strings into a value-level list of string. Used to turn the type-level list of template file names into a value-level list. !-. ! ! !-.None  !(c) Alp Mestanogullari 2015alpmestan@gmail.com experimentalNone'(2346=JKM " A list of #s.#A #H is a pair of a template filename and the error string for that file.$$An opaque "compiled-template store".4The only way to get a value of this type is to use ( on a proxy of your API.LThis ensures that when we lookup a template (in order to render it) in our $& store, we are guaranteed to find it.%Collect all the template filenames of an API as a type-level list of strings, by simply looking at all occurences of the ' and &: combinators and keeping the filenames associated to them.&&' content type, but more than just that.&r takes a type-level string which is a filename for the template you want to use to render values. Just like ', types used with the & content type (like User below) must provide a  instance.Example: ÿ\type UserAPI = "user" :> Get '[JSON, HTML "user.tpl"] User userAPI :: Proxy UserAPI userAPI = Proxy data User = User { name :: String, age :: Int } deriving Generic instance ToObject User server :: Server API server = return (User "lambdabot" 31) main :: IO () main = do loadTemplates userAPI "./templates" run 8082 (serve userAPI server) !This will look for a template at ./templates/user.tpl, which could for example be: b<ul> <li><strong>Name:</strong> {{ name }}</li> <li><strong>Age:</strong> {{ age }}</li> </ul> IMPORTANT,: it XSS-sanitizes every bit of text in the ) passed to the template.'jA generic template combinator, parametrized over the content-type (or MIME) associated to the template.rThe first parameter is the content-type you want to send along with rendered templates (must be an instance of /).^The second parameter is the name of (or path to) the template file. It must live under the 0 argument of (.+Any type used with this content-type (like CSSData( below) must have an instance of the K class. The field names become the variable names in the template world.-Here is how you could render and serve, say, CSS@ (Cascading Style Sheets) templates that make use of some CSSData data type to tweak the styling. ÿèdata CSS instance Accept CSS where contentType _ = "text" // "css" type StyleAPI = "style.css" :> Get '[Tpl CSS "style.tpl"] CSSData styleAPI :: Proxy StyleAPI styleAPI = Proxy data CSSData = CSSData { darken :: Bool , pageWidth :: Int } deriving Generic instance ToObject CSSData server :: Server API server = -- produce a CSSData value depending on whatever is relevant... main :: IO () main = do loadTemplates styleAPI "./templates" run 8082 (serve styleAPI server) !This will look for a template at ./templates/style.tpl, which could for example be: Åbody { {% if darken %} background-color: #222222; color: blue; {% else %} background-color: white; color: back; {% endif %} } #content { width: {{ pageWidth }}; margin: 0 auto; }:A complete, runnable version of this can be found in the examples folder of the git repository.(<This function initializes a global template store (i.e a $ª value) and fills it with the resulting compiled templates if all of them are compiled successfully. If that's not the case, the global template store (under an 1) is left empty. IMPORTANT: Must always be called before starting your servant application. Example: Žtype API = Get '[HTML "home.tpl"] HomeData api :: Proxy API api = Proxy main :: IO () main = loadTemplates api "path/to/templates" >>= printThis would try to load home.tpl…, printing any error or registering the compiled template in a global (but safe) compiled template store, if successfully compiled.2&XSS-sanitizes data before rendering it3 text/html;charset=utf-8%"#$456%78&'( root directory for the templates9 root directory for the templates:;<=>?@ABCDEFGHIJKLM23NO  "#$%&'( &'(% $"#$"#$456%78&'(9:;<=>?@ABCDEFGHIJKLM23NOP      !"#$%&'()*+,-./01234567/089:;<=>?@>ABCD*EFGHIJKLMNOPQRSTUVWXYZ[\]^_`servant-ede-0.5Servant.EDE.Internal.ValidateServant.EDE.Internal.ToObjectServant.EDE.Internal.Reify Servant.EDEServant.EDE.Internal ValidateTVT runValidateT ValidatedNotOKOKvalidateEithereitherValidateokno validatedvalidate$fSemigroupValidateT$fApplicativeValidateT$fFunctorValidateT$fSemigroupValidated$fTraversableValidated$fFoldableValidated$fApplicativeValidated$fFunctorValidated GToObject gtoObjectToObjecttoObjectgenericToObject $fGToObjectM1$fGToObjectM10$fGToObjectM11$fGToObject:*: $fGToObjectU1 $fGToObjectV1$fToObjectHashMapReifyreifyErrors TemplateError Templates TemplateFilesHTMLTpl loadTemplates aeson-0.9.0.1Data.Aeson.Types.InternalObjectunordered-containers-0.2.5.1Data.HashMap.BaseHashMap text-1.2.1.1Data.Text.InternalTextValue$fReify: $fReify[]servant-0.4.3.1Servant.API.ContentTypesAcceptbaseGHC.IOFilePathGHC.MVarMVar$fMimeRender*HTMLa $fAccept*HTMLCTFileCTFilesMemberAppendloadTemplates'__template_storesanitizeObject sanitizeKV sanitizeValue templates templateFiles templateMaptplerr processFile$fMonoidTemplates$fSemigroupTemplatesTFCo:R:TemplateFiles*RawTFCo:R:TemplateFiles*PutTFCo:R:TemplateFiles*PostTFCo:R:TemplateFiles*PatchTFCo:R:TemplateFiles*GetTFCo:R:TemplateFiles*DeleteTFCo:R:TemplateFiles*:>TFCo:R:TemplateFiles*:<|>$fMimeRender*Tpla $fAccept*Tpl