I am adding some function to threepenny ui api. I would like to had the ability to draw line with canvas.
The function that I can write have the following signature:
moveTo :: Vector -> UI ()
lineTo :: Vector -> UI ()
stroke :: UI ()
strokeStyle :: UI ()
beginPath :: UI ()
Each primitive moveTo
and lineTo
should happen in between a beginPath
.. stroke call.
How would you enforce the beginPath
... stroke sequence. By design I would like to give the user no choice for drawing lines. So the user is not aware of the beginPath
... stroke sequence.
Here's how I would design a canvas API.
newtype Drawing = ...
instance Monoid Drawing where ... -- for combining drawings
line :: Vector -> Vector -> Drawing
path :: [Vector] -> Drawing
withStyle :: Style -> Drawing -> Drawing
runDrawing :: Drawing -> UI ()
Here the functions operate on semantically meaningful objects (from the user's perspective), rather than imperative commands. This should be implementable with the type
newtype Drawing = Drawing (UI ())
however sometimes subtleties will require that the type have a bit more structure, so be open to that (e.g. Something -> UI ()
).