lucid-svg 0.7
Update
lucid-svg will not change. The new API will be released as svg-builder.
tl;dr
lucid-svg 0.7 will a breaking change that no longer depends on lucid. The code is on github but I’m holding off on putting it on hackage to give people some time to make suggestions.
Diverging from lucid
lucid-svg was created to address the short comings of blaze-svg in the same spirit as lucid was for blaze-html. After using lucid-svg for about a year now, it’s time to break free of Chris Done’s excellent lucid package. Some of the reasons that I am doing this is that SVG is different enough from html that using an html dsl as the core of lucid-svg is not the best way to go. The remaining justification is simply my personal taste. I want to say straight away, that this decision is in no way a knock of the lucid package, which I think is the best dsl for writing html that is available, in fact I use many of the key ideas from lucid in the lucid-svg 0.7.
Attributes are no longer created like elements.
In previous versions we set svg elements and attributes the same way: function application. For example if we wanted to create a width attribute we might write width_ "100%"
. The code to create a red rectangle would look something like this,
I prefer not to conflate elements and attributes by using the same syntax, so in lucid-svg 0.7 we set attributes using the “attribute assignment operator” like Width_ <<- "100%"
. This operator is called bindAttr
and can also be used flipped, "100% ->> Width_"
. So our previous example becomes:
The attributes are represented by value constructors ending in an underscore to minimize namespace collisions. This is certainly a bit more verbose, but I think worth it to distinguish between attributes and elements. Attributes can still be composed with the with
function.
No more monad instance
The monad instance in lucid, while a decided improvement over the one in blaze is overkill for my purposes. In lucid-svg it was only used to be able to replace monoidal append with do notation. I personally don’t find using <>
or mconcat
a burden. It always bothered me that the monad in lucid is typically used with a value of type unit, HtmlT m ()
or in lucid-svg SvgT m ()
, so we are always throwing away the value and just keeping the side effect. Hence, code that was previously written like this:
is now written like this:
If you really want to use do notation, you could always use the RebindableSyntax
language extension with (>>) = (<>)
.
Less polymorphism
Lucid uses a very overloaded type class so that functions can be used to create both attributes and elements depending on the arguments it is passed. And also to optionally supply a list of attributes as an argument and optionally pass a a child element. We don’t use function application any longer for creating attributes, so we don’t need this case. But more importantly, in SVG we are most often using attributes when creating elements and I’d rather be explicit and pass the empty list when there are no attributes. I did find passing mempty
to indicate no child element annoyoing, so we keep the polymorphism here. That is if there are no child elements we can simply leave out the last argument to the function call as we do when using rect_
and circle_
above, otherwise we include them like with text_
in the example. So now to create an element with no attributes we do,
Other small changes
Since doctype_
is not a function just an SVG element, it has been renamed doctype
.
The base type for an SVG element is now Element
, not Svg ()
.