Lately, I've been writing more functions that take an Attribute
collection as an argument. I'm trying to think of ways to make it easier to users (mostly myself) to call these functions. One strategy I've started adopting is accepting a Foldable
collection of Attribute
s. Here's an example from a library of mine:
footer_ :: (Monad m, Foldable t) => t Attribute -> WidgetT site m a -> WidgetT site m a
I know that blaze has the !
operator, but I've always preferred concatenating all of my Attribute
s first and then applying them to the element. And that's exactly what this function does. It uses the Foldable
instance just to call fold
on the collection. The end user ends up writing:
footer [class_ "foo", id_ "bar"] "Stuff in the footer"
I was thinking though that it's annoying to have the Foldable
constraint at all. It could be written to take a list of Attribute
s instead, but I still consider that an unneeded indirection. The function could alternatively be written as:
footer_ :: Monad m => Attribute -> WidgetT site m a -> WidgetT site m a
But then the user must call fold
(or mconcat
) manually:
footer (fold [class_ "foo", id_ "bar"]) "Stuff in the footer"
Which I don't want to have to do when writing code. All of this is the background for why I would like a FromList
instance. The instance I'm describing could technically exist for any Monoid
. It is written as:
class IsList Attribute where
type Item Attribute = Attribute
fromList = fold
toList x = [x]
The neat thing about this is that it would enable me to define footer_
to accept an Attribute
, and in the common use case (a list of attributes of known at compile time), the user doesn't have to call fold
manually:
footer_ :: Monad m => Attribute -> WidgetT site m a -> WidgetT site m a
footer_ = ...
>>> footer_ [class_ "bar", id_ "baz"] "Content"
The bad thing is that this instance does not satisfy the law fromList . toList = id
. However, given that users cannot inspect Attribute
s to discover their structure, I would argue that the law is satisfied "up to interpretation", similar to how certain monads only satisfy the monad laws under an interpretation function. Anyway, let me know what you think. Having this instance would be helpful for a lot of the stuff I'm working on.