Как я могу встроить текст и виджет в другой виджет в Yesod?

Приведенный простой пример, как это

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>|]

Есть ли встроенный механизм в Йесод, который позволил бы мне сделать оба foo "some text" а также foo (glyphicon "pencil")? Мне удалось обойти это с помощью пользовательского класса типов, который преобразует текст и виджет в виджет

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")} вместо.

Есть ли лучший способ вложения обоих Text а также Widget внутри другого Widget?

1 ответ

Решение

Я бы не пошел по этому пути, особенно из-за проблемы вывода типов, которую вы уже обнаружили. Явная необходимость иногда вызывать toWidget, вероятно, является лучшим компромиссом здесь.

Другие вопросы по тегам