Skip to content

Fix #83 by changing the choice of minNestingLevel#89

Merged
quchen merged 3 commits into
haskell-prettyprinter:masterfrom
sjakobi:min-nesting-line
Nov 5, 2019
Merged

Fix #83 by changing the choice of minNestingLevel#89
quchen merged 3 commits into
haskell-prettyprinter:masterfrom
sjakobi:min-nesting-line

Conversation

@sjakobi

@sjakobi sjakobi commented Oct 24, 2019

Copy link
Copy Markdown
Collaborator

No description provided.

@sjakobi

sjakobi commented Oct 24, 2019

Copy link
Copy Markdown
Collaborator Author

I'll try to explain this later… ;)

minNestingLevel = min lineIndent currentColumn
minNestingLevel = case y of
SLine _ _ -> lineIndent
_ -> currentColumn

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We check whether the second alternative (y) starts with a line break in order to detect hanging layouts as (partially) explained in #83 (comment).

@sjakobi sjakobi Oct 24, 2019

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The loss of laziness in y is a bit unfortunate. Since best seems to be quite lazy, I hope it's not too bad though.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The loss of laziness in y is a bit unfortunate.

I think this is probably outweighed by the efficiencies gained from the greater minNestingLevel when we select currentColumn:

  • We don't have to check x as far as with lineIndent.
  • We can more often stick with x instead of switching to y.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If y starts with one of the annotation constructors, we should probably look further for the first "proper" constructor…

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went with the »annotations might mean something important even if they contain something unimportant« elsewhere (strip trailing whitespace), so I think ignoring annotations here is alright. What do you think?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm actually not really familiar with how annotations work or how they are used.

But it seems to me that the result of layoutWadlerLeijen should not depend on the presence of annotations. Wouldn't the following property be desirable?

layoutWadlerLeijen fp opts (unAnnotate doc) === unAnnotateS (layoutWadlerLeijen fp opts doc)

So I think it would be better to check what's behind the annotations.

@quchen

quchen commented Oct 25, 2019

Copy link
Copy Markdown
Collaborator

Ha nice! At first I was concerned about your pattern matching on y, but then realized it’s a SimpleDoc, not a Doc, so matching is well-behaved and not just a hack that works in case the rest of the document is already normalized.

I agree the loss of laziness in y is unfortunate, but on the other hand selecting the nicer of two alternatives kind of has comparison between two things built in. I was actually surprised quite a few times that the library could away with looking only at the first alternative.

I’ll add another test to make sure layoutPretty isn’t affected after having another look at this at home this weekend, and make a release.

Thanks for all your work! I’m not sure how long it would have taken me to spot this one…

Comment thread prettyprinter/src/Data/Text/Prettyprint/Doc/Internal.hs Outdated
@sjakobi sjakobi changed the title Draft: Fix #83 by changing the choice of minNestingLevel Fix #83 by changing the choice of minNestingLevel Oct 25, 2019
-- See https://github.com/quchen/prettyprinter/issues/83.
if startsWithLine y
-- y might be a (more compact) hanging layout. Let's check x
-- thoroughly with the smaller lineIndent.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we wanted to detect hanging layouts more precisely, we could also check that the indentation of the SLine is < currentColumn. But what we have right now is the slightly more conservative change.

| fits pWidth minNestingLevel availableWidth x = x
| otherwise = y
where
minNestingLevel = min lineIndent currentColumn

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any idea why this was computed with min and didn't just return lineIndent?

Doesn't the invariant from above hold here?

-- * current column >= current nesting level

-- y definitely isn't a hanging layout. Let's allow the first
-- line of x to be checked on its own and format it consistently
-- with subsequent lines with the same indentation.
else currentColumn

@sjakobi sjakobi Oct 26, 2019

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are the general conditions under which layoutSmart, given a Union x y, will change its behaviour to return x instead of y with this change:

  • y doesn't start with a line break
  • lineIndent must be < currentColumn
  • a line of x (but not the first) with an indentation of lineIndent < i <= currentColumn is too wide.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • a line of x (but not the first) with an indentation of lineIndent < i <= currentColumn is too wide.

Actually that line must be "reachable" too. I.e. there's no other line with an indentation <= lineIndent before it.

@sjakobi

sjakobi commented Oct 30, 2019

Copy link
Copy Markdown
Collaborator Author

@quchen Did you get a chance to look at this further?

Ideally I'd like to smoke-test this patch in projects that are likely to be impacted. Do you know any suitable projects?

The next best thing would IMHO be to just release this and wait for feedback. :)

@quchen

quchen commented Nov 5, 2019

Copy link
Copy Markdown
Collaborator

Released 1.5. I don’t have that much time on my hands right now, sorry for the delays!

@sjakobi sjakobi deleted the min-nesting-line branch November 5, 2019 12:15
@sjakobi

sjakobi commented Nov 5, 2019

Copy link
Copy Markdown
Collaborator Author

No worries. Thanks for the releases! :)

@sjakobi sjakobi mentioned this pull request Nov 6, 2019
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