単純に関数に代入してhtmlを作ってみたがお世辞にも簡潔には書けなかった。。

import Data.List

main = putStrLn html

tag_doctype = "<!DOCTYPE html>
"
tag_html txt = "
<html>
" ++ txt ++ "
</html>
"
tag_head txt = "
<head>
" ++ txt ++ "
</head>
"
tag_body txt = "
<body>
" ++ txt ++ "
</body>
"
tag_title txt = "
<title>
" ++ txt ++ "
</title>
"
tag_meta charset = "
<meta charset=" ++ charset ++ ">
"
tag_header txt = "
<header class=header>
" ++ txt ++ "
</header>
"
tag_footer txt = "
<footer class=footer>
" ++ txt ++ "
</footer>
"
tag_div cls txt = "
<div class="++cls++">
" ++ txt ++ "
</div>
"
tag_main cls txt = "
<main class=" ++cls++ ">
" ++ txt ++ "
</main>
"
tag_style txt = "
<style type=text/css>
" ++ txt ++ "
</style>
"
tag_h1 cls txt = "
<h1 class=" ++cls++ ">
" ++ txt ++ "
</h1>
"
tag_h2 cls txt = "
<h2 class=" ++cls++ ">
" ++ txt ++ "
</h2>
"
tag_h3 cls txt = "
<h3 class=" ++cls++ ">
" ++ txt ++ "
</h3>
"
tag_p cls txt = "
<p class=" ++cls++ ">
" ++ txt ++ "
</p>
"
tag_time cls datetime txt = "
<h3 class=" ++cls++ " datetime=" ++datetime++ ">
" ++ txt ++ "
</h3>
"



tag_a cls href txt = "
<a class=" ++cls++ " href=" ++href++ ">
" ++ txt ++ "
</a>
"
tag_nav cls txt = "
<nav class=" ++cls++ ">
" ++ txt ++ "
</nav>
"
tag_ul cls txt = "
<ul class=" ++cls++ ">
" ++ txt ++ "
</ul>
"
tag_li cls txt = "
<li class=" ++cls++ ">
" ++ txt ++ "
</li>
"
tag_img cls src alt =  "
<img class=" ++cls++ "" ++" src=" ++ src ++ " alt=" ++ alt ++ ">
"
tag_link rel href = "
<link rel=" ++ ""++ rel ++"" ++ " href=" ++ href ++ ">
"
tag_span cls txt = "
<span class=" ++cls++ ">
" ++ txt ++ "
</span>
"



hiragino = "Hiragino Kaku Gothic ProN, Meiryo, sans-serif"
fontsize txt = "font-size:" ++ txt ++ ";"
font_weight txt = "font-weight:" ++ txt ++ ";"
font_family txt = "font-family:" ++ txt ++ ";"
box_sizing txt = "box-sizing:" ++ txt ++ ";"
text_decoration txt = "text-decoration:" ++ txt ++ ";"
padding txt = "padding:" ++ txt ++ ";"
color txt = "color:" ++ txt ++ ";"
background txt = "background:" ++ txt ++ ";"
background_color txt = "background-color:" ++ txt ++ ";"
box_shadow txt = "box-shadow:" ++ txt ++ ";"
width txt = "width:" ++ txt ++ ";"
height txt = "height:" ++ txt ++ ";"
margin txt = "margin:" ++ txt ++ ";"
margin_top txt = "margin-top:" ++ txt ++ ";"
margin_bottom txt = "margin-bottom:" ++ txt ++ ";"
opacity txt = "opacity:" ++ txt ++ ";"
float txt = "float:" ++ txt ++ ";"
top txt = "top:" ++ txt ++ ";"
left txt = "left:" ++ txt ++ ";"
position txt = "position:" ++ txt ++ ";"

overflow txt = "overflow:" ++ txt ++ ";"
text_indent txt = "text-indent:" ++ txt ++ ";"
text_align txt = "text-align:" ++ txt ++ ";"

white_space txt = "white-space:" ++ txt ++ ";"
display txt = "display:" ++ txt ++ ";"

line_height txt = "line-height:" ++ txt ++ ";"
border_radius txt = "border-radius:" ++ txt ++ ";"
letter_spacing txt = "letter-spacing:" ++ txt ++ ";"
transition txt = "transition:" ++ txt ++ ";"





csscls::String->[String]->String
csscls cls props = cls ++ " {
" ++ (intercalate "
" props) ++ "
}
"


tag_canvas txt = "<canvas id=canvas width=200 height=200>
" ++ txt ++ "
</canvas>"
tag_script txt = "<script>n" ++ txt ++ "n</script>"






-------------------- カスタマイズ部分

-- css設定
css::String
css = tag_style (intercalate "
" [
  csscls ".header" [
                  "width:100%;",
                  padding "28px 0 10px",
                  background "url(./e.png) repeat-x",
                  box_shadow "0 0 10px 1px #e3e3e3"
    ],
  csscls ".wrapper" ["width:970px;","margin: 30px auto 40px;"],
  csscls ".main" ["display:block;","float:left;","width:80%;"],
  csscls ".sidemenu" ["float:right;","width:20%;"],
  csscls ".footer" ["width:100%;"],
  csscls ".clearfix::after" ["content:;","display:block;","clear:both;"],
--  csscls ".header, .main, .sidemenu, .footer" ["border: 1px solid #aaa;","background-color:#ccc;"],
--  csscls ".header, .footer" ["height:100px;"],
--  csscls ".main, .sidemenu" ["height:500px;"],
  csscls "html" [fontsize "62.5%"],
  csscls "body" [color "#333", fontsize "1.2rem", font_family hiragino],
  csscls "*,*::before *::after" [box_sizing "border-box"],
  csscls "a:link a:visited a:hover a:active" [color "#d03c56",text_decoration "none"],
  csscls ".logo" [width "225px",
                  height "56px",
                  margin "0 auto", -- 中央寄せ
                  background "url(./logo.gif) no-repeat",
                  overflow "hidden", -- テキスト隠し
                  text_indent "100%", -- テキスト隠し
                  white_space "nowrap"
                  ],
  csscls ".logo a" [display "block", -- width,heightの指定をきかせるため(aはこれがinline)
                    width "100%",
                    height "100%"],
  csscls ".hidden" [display "none"],
  navicss,
  maincss
  ])

---------

html = commonMake "title" css header footer wrapper


-- 共通
commonMake title css header footer x = result where
  result = tag_doctype ++ html
  html = tag_html (head ++ body)
  head = tag_head (meta ++ title ++ (tag_link "stylesheet" "reset200802") ++ css)
  meta = tag_meta "UTF-8"
  title = tag_title "title"
  body = tag_body (header ++ x ++ footer)

-- ヘッダー
header::String
header = tag_header (logo ++ navi)

-- フッター
footer::String
footer = tag_footer ""

-- ラッパー
wrapper = tag_div "wrapper clearfix" (maincontents ++ (tag_div "sidemenu" ""))


-- ロゴ
logo = tag_h1 "logo" (tag_a "" "/" "Logo")

-- ナビ
navi = tag_nav "global-nav" list where
  list = tag_ul "" (intercalate "
" contents) where
    contents = [tag_li "nav-item active" (tag_a "" "#" "HOME"),
                tag_li "nav-item" (tag_a "" "#" "ABOUT"),
                tag_li "nav-item" (tag_a "" "#" "NEWS"),
                tag_li "nav-item" (tag_a "" "#" "TOPICS"),
                tag_li "nav-item" (tag_a "" "#" "DOCS"),
                tag_li "nav-item" (tag_a "" "#" "BLOG")]

navicss = (intercalate "
" [center, align_x, link, linkdynamics]) where
  center = csscls ".global-nav" [margin_top "15px",
                                 text_align "center" -- 子も中央寄せになる
                        ]
  align_x = csscls ".global-nav .nav-item" [
            display "inline-block", -- 横に並ぶ
            margin "0 10px"
            -- 高さしていいてないのでアイテムの高さはaによる
          ]
  link = csscls ".global-nav .nav-item a" [
            display "inline-block", -- 幅と高さ指定の有効化
            width "100px",
            height "30px",
            line_height "30px", -- 行の高さをheightと同じにして縦方向の中央よせ
            text_align "center", -- 横方向の中央よせ
            border_radius "8px",
            color "#666",
            fontsize "1.3rem",
            letter_spacing "1px", -- 文字間隔
            transition "0.15s"
          ]
  linkdynamics = csscls ".global-nav .nav-item.active a, .global-nav .nav-item a:hover" [
    background_color "#d03c56",
    color "#fff"
    ]


-- メイン
maincontents = tag_main "main" (hot ++ news ++ articles) where
  hot = title ++ body where
    title = tag_h2 "hidden" "HOT TOPIC"
    body = hottopic
  news = title ++ body where
    title = tag_h2 "" "NEWS"
    body = tag_div "news" newstopic
  articles = title ++ body where
    title = tag_h2 "hidden" "ARTICLES"
    body = tag_div "articles" "内容"

-- 子がflowなので親にclearfix付与
hottopic = tag_a "hot-topic clearfix" "#" (intercalate "
" [image,div]) where
  image = tag_img "image" "./logo.gif" "画像"
  div = tag_div "content" content where
    content = (intercalate "
" [title,desc,time]) where
      title = tag_h3 "title" "実務で使えるHTML/CSS<br>モダンコーディングTIPS"
      desc = tag_p "desc" "Webフロントエンドの進化の勢いは留まるところをしりません。"
      time = tag_time "date" "2017-06-02" "2017.06.02"

maincss = (intercalate "
" [hottpiccss])

hottpiccss = (intercalate "
" [common, hover, image, content]) where
  common = csscls ".hot-topic" [
    display "block",
    height "300px",
    margin_bottom "30px",
    box_shadow "0 6px 4px -4px rgba(0,0,0,0.15)",
    transition "opacity 0.15s"
    ]
  hover = csscls ".hot-topic:hover" [
    opacity "0.85"
    ]
  image = csscls ".hot-topic .image" [
    float "left",
    width "50%",
    height "100%"
    ]
  content = (intercalate "
" [base, title, desc, date]) where
    base = csscls ".hot-topic .content" [
      float "left",
      width "50%",
      height "100%",
      padding "25px 0",
      background_color "#2d3d54",
      position "relative", -- 子は相対座標
      line_height "1.6" -- フォントサイズ✕1.6
      ]
    title = csscls ".hot-topic .title" [
      margin_bottom "15px",
      color "#fff",
      font_weight "normal",
      fontsize "2.0rem"
      ]
    desc = csscls ".hot-topic .desc" [
      color "#ddc"
      ]
    date = csscls ".hot-topic .date" [
      position "absolute",
      top "0px",
      left "0px",
      width "140px",
      padding "4px",
      background_color "#fff",
      color "#2d3d54",
      letter_spacing "1px",
      font_weight "bold",
      fontsize "1.1rem",
      line_height "1"
      ]

-- news
newstopic = tag_ul "scroll-list" items where
  items = tag_li "scroll-item" (tag_a "" "#" (intercalate "
" [
    newslist "2017-06-01" "2017.06.01 WED" "TOPIC" "CSSでここまでできる!?",
    newslist "2017-06-02" "2017.06.02 WED" "TOPIC" "CSSでここまでできた!?",
    newslist "2017-06-03" "2017.06.03 WED" "TOPIC" "CSSでここまでできます!?"
    ]))

newslist datetime datetimestr categorystr titlestr = tag_li "scroll-item" (tag_a "" "#" (intercalate "
" [time, category, title])) where
  time = tag_time "date" datetime datetimestr
  category = tag_span "category" categorystr
  title = tag_span "title" titlestr