It seems like a major wart that often, in order to compose diagrams in a certain desired way, one must first perform an alignment (a destructive update, in the information-theoretic sense) before composing. The original alignment/local origin has to be explicitly saved and restored if that's what you want. I'd like to have some combinators that automatically do this for you.
For example, one might be able to write
hcat' (with & alignment .~ alignT) [d1,d2,d3] which would yield the same result as
hcat . map alignT $ [d1,d2,d3], except that the local origin of the result would be at the local origin of
d1, rather than that of
d1 # alignT.
On one level this is not hard to achieve. There is a sensible
instance Alignable a => Alignable (Located a) (omitted as an oversight until now, but I plan to add it soon, regardless of the outcome of the rest of this page); by applying an alignment function to
x `at` origin and inspecting the location of the result, one can learn how the alignment function would translate
x if applied directly. The problem is that this means the alignment function must be applied at two different types (once to learn the translation and once to do the actual alignment), and it is very hard (probably impossible) to come up with a nice most general polymorphic type of all alignment functions, since e.g. some require
Traced and some do not. That is, specifically, it is hard to imagine what type we could give to the hypothetical lens
alignment in the example above that would actually allow this to work.
One potential solution is to make a deeply embedded DSL of alignments (i.e. an algebraic data type representing different alignments) which can be interpreted to produce an alignment function at any desired
Alignable type. The downsides are that this may be a bit unwieldy for users, and it limits the potential alignment functions usable to exactly the list we have thought of right now.