Given a simple example like this
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>|]
Is there a builtin mechanism in Yesod which would allow me to do both foo "some text"
and foo (glyphicon "pencil")
? I've managed to work around this by using a custom typeclass which converts both Text and Widget to 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>|]
but this doesn't feel right, especially since I can't even do ^{foo "hello"}
due to ambiguous types, and have to do ^{foo (T.pack "hello")}
instead.
Is there a better way of embedding both Text
and Widget
inside another Widget
?
I wouldn't go this route, specifically because of the type inference issue you already discovered. Explicitly having to call toWidget occasionally is probably the best compromise here.