edeはHaskellの軽量テンプレート言語です。edeのルールに従って書かれたテキストにHaskellのデータ構造を使ってレンダリングしてテキストを生成することが出来ます。実際は主にHTMLページの生成とかに使うんだと思います。
HTMLの生成はHaskellではshakespeare, blaze-html, lucidなどが有名ですがどれも書き方が独特です。エンジニア以外の人と作業する場合はHTMLは出来るだけそのままに最低限のテンプレートの記法で済むようなものがいいでしょう。edeはMustacheベースのテンプレートでHaskeller以外の人にもわかりやすいものになっています。
例えばHTMLでこういうテーブルを表示するとしましょう。データはHaskell側から渡します。
data Todo = Todo
{ title :: String
, done :: Bool
}
todos :: [Todo]
todos = [ Todo "買い物に行く" False
, Todo "ゲームをする" True
, Todo "Haskellを書く" True
]
さっそくedeのテンプレートを書きます
<!DOCTYPE html>
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<table border="1">
<tr>
<th>#</th>
<th>Title</th>
<th>Done</th>
</tr>
{% for todo in todos %}
<tr>
<td>{{ todo.index }}</td>
<td>{{ todo.value.title }}</td>
<td>
{% if todo.value.done %}
✔
{% else %}
✗
{% endif %}
</td>
</tr>
{% endfor %}
</table>
</body>
</html>
ほとんどHTMLのままで必要なところだけテンプレート記法が使われてるのがわかると思います。Spockを使って実際にWebサーバー経由で表示してみるプログラムを書いてみます。
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE DeriveGeneric #-}
module Main where
import Data.Aeson
import Data.Text.Lazy (toStrict)
import GHC.Generics
import Text.EDE
import Web.Spock
data Todo = Todo
{ title :: String
, done :: Bool
} deriving Generic
instance ToJSON Todo
todos :: [Todo]
todos = [ Todo "買い物に行く" False
, Todo "ゲームをする" True
, Todo "Haskellを書く" True
]
main :: IO ()
main = do
tpl <- eitherParseFile "index.html"
let env = fromPairs [ "title" .= ("TODOリスト" :: Value)
, "todos" .= toJSON todos ]
body = either error toStrict $ tpl >>= (`eitherRender` env)
runSpock 3000 . spockT id $ do
get "/" $ html body
edeのテンプレートに渡すパラメータはAesonのObjectである必要があるのでTodo
はToJSON
のインスタンスになっています。実行してhttp://localhost:3000にアクセスすると先ほどのテーブルが表示されると思います。
HaskellにはlucidのようにモナドでHTMLを組み立てられるようなDSLもあって便利な一方で実際の開発ではHTMLはいろんな人がさわると思うのでedeのように薄いテンプレート言語が必要になるのだと思います。適材適所で使い分けていきたいですね