在哈姆雷特模板中使用紧凑的if-then-else

Nor*_*ius 0 haskell yesod hamlet shakespeare-text

我试图了解Yesod的Hamlet中的变量插值,特别是实现if-then-else-like逻辑.假设我想根据整数的值添加CSS样式x.它x来自模板中的for循环,即我无法从Haskell代码访问它.

期望的结果:

<span class="even positive">2</span>
<span class="odd positive">13</span>
<span class="odd non-positive">-1</span>
<span class="even non-positive">0</span>
Run Code Online (Sandbox Code Playgroud)

尝试内联if:

<span class="#{if even x then "even" else "odd"} ...">#{x}</span>
Run Code Online (Sandbox Code Playgroud)

尝试使用$with:

$with cls <- (if even x then "even" else "odd")
    <span class="#{cls}">#{x}</span>
Run Code Online (Sandbox Code Playgroud)

都不起作用; 两者都导致了

• Illegal variable name: ‘if’
  When splicing a TH expression
Run Code Online (Sandbox Code Playgroud)

显然,Haskell语法的一部分未在#{...}解析器中实现.有干净的方法吗?我现在只能看到一条出路,它很丑陋地狱:

$if ((even x) && (x > 0))
    <span class="even positive">#{x}</span>
$elseif (even x)
    <span class="even non-positive">#{x}</span>
$elseif (x > 0)
    <span class="odd positive">#{x}</span>
$else
    <span class="odd non-positive">#{x}</span>
Run Code Online (Sandbox Code Playgroud)

Dar*_*nec 5

这些模板表达式中不支持大多数Haskell语法.我认为这是设计,因为您不希望您的模板包含复杂的业务逻辑.

我会将代码编写为Haskell端的函数,并从模板中调用它.就像是:

-- .hs file
altclass, signclass :: Int -> String
altclass x = if even x then "even" else "odd"
signclass x = if x > 0 then "positive" else "non-positive"

-- .hamlet file
<span class="#{altclass x} #{signclass x}">#{x}</span>
Run Code Online (Sandbox Code Playgroud)

这样做可以正确地将业务逻辑从模板中分离出来,但仍允许您使用模板内变量.