如何在Yesod中的另一个Widget中嵌入Text和Widget?

时间:2015-02-14 13:41:25

标签: haskell yesod hamlet

给出一个像这样的简单例子

glyphicon :: Text -> Widget
glyphicon name = toWidget [hamlet|<span class="glyphicon glyphicon-#{name}">|]

foo :: ToMarkup a => a -> Widget
foo content = toWidget [hamlet|<div class="foo">#{content}</div>|]

Yesod中是否有内置机制允许我同时执行foo "some text"foo (glyphicon "pencil")?我设法通过使用自定义类型类来解决这个问题,该类型类将Text和Widget转换为Widget

class MakeWidget a where
  makeWidget :: a -> Widget

instance MakeWidget Widget where
  makeWidget = id

instance MakeWidget Text where
  makeWidget x = toWidget [hamlet|#{x}|]

glyphicon :: Text -> Widget
glyphicon name = toWidget [hamlet|<span class="glyphicon glyphicon-#{name}">|]

foo :: MakeWidget a => a -> Widget
foo content = toWidget [whamlet|<div class="foo">^{makeWidget content}</div>|]

但这感觉不对,特别是因为模糊的类型我甚至无法做^{foo "hello"},而是必须做^{foo (T.pack "hello")}

是否有更好的方法将TextWidget嵌入另一个Widget

1 个答案:

答案 0 :(得分:1)

我不会走这条路,特别是因为您已经发现的类型推断问题。偶尔必须偶尔调用Widget可能是最好的妥协。