Text Templates in Haskell

In Haskell, we can use libraries like text-templates or mustache for templating. For this example, we’ll use text-templates as it’s closer to Go’s text/template package in functionality.

First, let’s start with the basic structure and imports:

import qualified Data.Text as T
import qualified Data.Text.IO as TIO
import Text.Template

main :: IO ()
main = do

We can create a new template and parse its body from a string. Templates are a mix of static text and “variables” enclosed in {{...}} that are used to dynamically insert content.

    let t1 = parse "Value is {{value}}\n"
    case t1 of
        Left err -> error $ show err
        Right template -> do
            -- Render the template with different values
            TIO.putStr $ substitute template (Context [("value", T.pack "some text")])
            TIO.putStr $ substitute template (Context [("value", T.pack $ show (5 :: Int))])
            TIO.putStr $ substitute template (Context [("value", T.pack $ show ["Haskell", "Rust", "C++", "C#"])])

If the data is a record (similar to a struct in Go), we can use field names directly in the template:

    let t2 = parse "Name: {{name}}\n"
    case t2 of
        Left err -> error $ show err
        Right template -> do
            TIO.putStr $ substitute template (Context [("name", T.pack "Jane Doe")])
            TIO.putStr $ substitute template (Context [("name", T.pack "Mickey Mouse")])

For conditional execution, we can use {{#if}} and {{#unless}} in our templates:

    let t3 = parse "{{#if value}}yes{{#unless value}}no{{/unless}}\n"
    case t3 of
        Left err -> error $ show err
        Right template -> do
            TIO.putStr $ substitute template (Context [("value", T.pack "not empty")])
            TIO.putStr $ substitute template (Context [("value", T.pack "")])

For looping through lists, we can use {{#each}} in our templates:

    let t4 = parse "Range: {{#each items}}{{.}} {{/each}}\n"
    case t4 of
        Left err -> error $ show err
        Right template -> do
            TIO.putStr $ substitute template (Context [("items", map T.pack ["Haskell", "Rust", "C++", "C#"])])

To run this program, you would need to install the text-templates package and compile the code:

$ cabal install text-templates
$ ghc -o templates templates.hs
$ ./templates
Value is some text
Value is 5
Value is ["Haskell","Rust","C++","C#"]
Name: Jane Doe
Name: Mickey Mouse
yes
no
Range: Haskell Rust C++ C# 

This example demonstrates how to use text templates in Haskell, which provides similar functionality to Go’s text/template package. The syntax and exact features may differ, but the core concept of separating templates from data remains the same.