Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generalise vertical- and horizontal concatenation beyond the diagrams use case #94

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

leftaroundabout
Copy link

@leftaroundabout leftaroundabout commented Oct 28, 2017

Diagrams has a nice Juxtaposable class that allows composing in arbitrary direction, and that is by nature pretty specific to diagrams. But much of the work in typical applications is actually done in only two discrete directions, horizontal and vertical, and that's something which is also done in many other applications. Apart from diagrams, it's obviously relevant for document layout, but also for matrices (though, that should arguably better be expressed in a more strongly-typed manner...).

But AFAIK each of these applications, Diagrams included, has only defined operators like === and ||| on an ad-hoc basis.

While designing a CSS-grid based presentation eDSL, I decided to not invent that wheel yet again, and instead gave the concatenation operators a general-purpose class, namely, a numbered sequence of semigroup classes.

I've put that in a small library just for the single class. Now I wonder if we could actually make QDiagram an instance of that class, and thus use the same operators both for diagrams and for other multidirectional-concatenatable stuff? This would be particularly useful for said eDSL since I'd like to compose both diagrams and other content in a single file, without awkward qualified names.

I'd appreciate any opinion!

These classes offer an interface for what has already been implemented with
the `===` and `|||` operators, in a manner that's independent of diagrams.
@byorgey
Copy link
Member

byorgey commented Nov 13, 2017

Hi there, apologies for taking so long to respond. I am fine with this in principle, but I think I'd want to see a few more things before depending on it:

  1. What are the laws associated with SemigroupNo? I assume any particular SemigroupNo n should be a semigroup. But what about interactions between different n? I'd love to be able to impose some sort of commutativity/abides law (e.g. (a === b) ||| (c === d) == (a ||| c) === (b ||| d))... except actually that law doesn't hold for diagrams. Are there any laws at all that we can state? Perhaps if some type g is an instance of SemigroupNo n and also a Monoid, then its identity element should be the identity for all n? (e.g. notice how the empty diagram is the identity for both vertical and horizontal composition... hmm, though it seems like this isn't true for [[a]]. Should it be? What about for hmatrix?)

  2. More examples and explanation in the documentation would be nice... though I suppose in the end if all we're doing is adding some instances to diagrams it is not that big of a deal, users can just ignore these instances if they want.

@leftaroundabout
Copy link
Author

Thanks for the reply.

I already thought myself about whether sappendN p mempty a ≡ a ≡ sappendN p a mempty should always hold. The list instances are in fact defined with that in mind; they do kind of fulfill this identity – just, modulo extra padding. E.g.

Prelude Data.Semigroup.Numbered> mempty ||| ["bla","blip","blumm"]
["bla","blip","blumm"]
Prelude Data.Semigroup.Numbered> ["bla","blip","blumm"] === mempty
["bla  ","blip ","blumm"]

I'm just not sure if this law is really that much use, and if it doesn't preclude some other reasonable instances. So, that, together with the fuzzy “modulo padding” caveat, stopped me from formulating the law explicitly so far.

About documentation/examples you're right of course; I should add some.

@byorgey
Copy link
Member

byorgey commented Nov 21, 2017

OK, fair enough (re: laws).

Just to make sure I understand, diagrams users should in general be unaffected by this change; if one wanted to make use of it (e.g. to use (|||) and friends at several types in the same code, as you mentioned), one would import Diagrams.Prelude hiding ((|||), (===)) and then import them from Data.Semigroup.Numbered --- is that correct?

@leftaroundabout
Copy link
Author

Yes, that was my idea: users would not be affected in any way save for slightly longer build times. I won't add any dependencies to numbered-semigroups, so it'll never be much.

(I certainly also wouldn't mind if diagrams re-exported numbered-semigroups instead of defining its own operators, but there's not much of a difference here.)

@byorgey
Copy link
Member

byorgey commented Nov 28, 2017

Another question: do you know which version of GHC is needed to support the type-level natural number literals?

@leftaroundabout
Copy link
Author

It needs at least GHC-7.6, but actually I've only tested it with >=7.10 so far. I'll add a Travis build later today to try older versions and relax the base dependency accordingly.

@leftaroundabout
Copy link
Author

So after a couple of legacy patches (mostly related to the AMP and FTP), the library now compiles on GHC ∊ {7.6, 7.8, 7.10, 8.0, 8.2}. The type-numbers aren't a problem. (They might become a problem if I did actual arithmetic with the types, but at least at the moment those numbers are basically just static identifiers.)

https://travis-ci.org/leftaroundabout/numbered-semigroups/builds/308951619

@byorgey
Copy link
Member

byorgey commented Nov 30, 2017

OK, let me know when you've uploaded it to Hackage. At the moment diagrams-core builds all the way back to GHC 7.4 but I'm perfectly fine with dropping 7.4 support (in fact I'm quite sure some of the downstream diagrams packages don't support GHC 7.4 anyway).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants