I’ve finally sat down and played with Brent Yorgey’s diagrams package. Every once in a while, I just want to write something fun–some feel good code. Well, I had so much fun, I want to describe what I made.
It’s nothing complex or strange, it’s just a few shapes with some colors! (But the colors are so shiny and happy!)
Lets start from the top:
numCols, numRows :: Int
numCols = 23
numRows = 5
Here, we just defined how many shapes wide and how many shapes tall we want our resulting diagram to be. Lets define main next:
main :: IO ()
main = renderAs SVG "out2.svg" (Width width) dgram
where width = (fromIntegral numCols) * 30
Alright, we know what numCols is, and we see width defined in the where clause, but what is dgram?
dgram :: Diagram
dgram = vcat $ take numRows rows
where rows = map hcat $ plines crps
dgram is the top level diagram we’re rendering. vcat is a vertical concatenation of several other diagrams. We take a specific number of rows from rows–the horizontal concatenation (hcat) of whatever is generated by plines crps–and concatenate them together vertically.
Alright, we seem to be almost there now. What is plines?
plines :: [Diagram] -> [[Diagram]]
plines [] = []
plines pls = let (l,ls) = splitAt numCols pls
in l : (plines ls)
As it turns out, plines is just a cheap chunking function with a fixed chunk size. All this does is turn a list into a list of lists with the same length. If the sublists were concatenated back together again, you’d have your original list.
We’ve seen everything plines has to offer, what about crps?
crps :: [Diagram]
crps = zipWith fillColor cs rps
where rps = zipWith rotate rs ps
rs = cycle . map (/ 4) $ [1..4] -- 4 rotations
ps = cycle . map (flip regPoly 1) $ [3..7] -- 5 polygons
cs = cycle [red,black,green,blue,yellow,violet] -- 6 colors
Hey! This is more interesting! Lets look a little closer at what’s happening here.
The ps symbol defines an infinite list of cycling polygons. We use the regular polygon (regPoly) function to generate polygons with 3, 4, 5, 6, and 7 sides. The cs symbol is just defining an infinite list of colors–nothing too complex here. The rs symbol is a cycling list of 1/4, 2/4, 3/4, and 4/4. These are used as rotations in terms of turns.
Now, what is that rps symbol? Lets see, we are zipping rs and ps together using the function rotate which accepts a Double representing a fraction of a turn and a Diagram to rotate. So, rps is an infinite list of cycling polygons where each successive polygon is rotated one quarter turn more than the previous.
This means that crps is an infinite list of cycling polygons each rotated one quarter turn more than the previous polygon but and each polygon has a cycling fill color! Neat!
So what does this look like?

I don’t know about you, but that takes me back to grade school. Sometimes a little bit of happy code can brighten your day!
Links to source files and SVG images:
Original, not quite as cool, attempt and its SVG rendering.
Finished colorful one and its SVG rendering.