Как я могу встроить текст и виджет в другой виджет в 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, вероятно, является лучшим компромиссом здесь.