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

New Some/None constructors for Optional values #227

Merged
merged 4 commits into from
Sep 7, 2018

Conversation

Gabriella439
Copy link
Contributor

@Gabriella439 Gabriella439 commented Sep 1, 2018

... as discussed in #113 (comment)

This adds new Some/None constructors that will (eventually) displace the
List-like syntax for Optional values.

The key new feature is that Some does not require you to supply the element
type. In other words, you can now write Some 1 instead of [ 1 ] : Optional Integer.

The second benefit is that the new constructors are just shorter in general.

This proposes that Some/None are the new normal forms for optional literals
and that the legacy List-like syntax β-normalizes to Some/None. The
reason why is that converting in the opposite direction from Some t to
[ t ] : Optional T would require performing type inference during
β-normalization (which would complicate β-normalization). In contrast,
converting from [ t ] : Optional T is straightforward and only requires
dropping the type.

Eventually the legacy List-like syntax will be dropped after a suitably
long migration period.

... as discussed in #113 (comment)

This adds new `Some`/`None` constructors that will (eventually) displace the
`List`-like syntax for `Optional` values.

This proposes that `Some`/`None` are the new normal forms for optional literals
and that the legacy `List`-like syntax β-normalizes to `Some`/`None`.  The
reason why is that converting in the opposite direction from `Some t` to
`[ t ] : Optional T` would require performing type inference during
β-normalization (which would complicate β-normalization).  In contrast,
converting from `[ t ] : Optional T` is straightforward and only requires
dropping the type.

Eventually the legacy `List`-like syntax will be dropped after a suitably
long migration period.


encode-1.0(t₀) = t₁ encode-1.0(T₀) = T₁
────────────────────────────────────────────────
encode-1.0([ t₀ ] : Optional T₀) = [ 5, T₁, t₁ ]


encode-1.0(t₀) = t₁
─────────────────────────────────────
encode-1.0(Some t₀) = [ 5, null, t₁ ]
Copy link
Collaborator

Choose a reason for hiding this comment

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

The decoding judgement will need to learn about the null here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, whoops, yes. I also forgot to bump the protocol version string to "1.1" and other related changes

@vmchale
Copy link

vmchale commented Sep 1, 2018

This sounds wonderful! It would simplify the parser as well :)

Gabriella439 added a commit to dhall-lang/dhall-haskell that referenced this pull request Sep 1, 2018
... as standardized in dhall-lang/dhall-lang#227

The legacy `Optional` syntax is still supported for now but the normal form for `Optional`
literals now prefers `Some`/`None`.

The `dhall lint` command will automatically migrate the old `Optional` literal syntax to the
new syntax.
@Gabriella439
Copy link
Contributor Author

Here's the matching pull request for the Haskell implementation: dhall-lang/dhall-haskell#559

@f-f
Copy link
Member

f-f commented Sep 1, 2018

@Gabriel439 this is cool 👏 👏

About your concerns in #113 (comment):

  • Present/Absent: I agree with your analysis but I think it presents more compelling reasons to go with Some/None rather than with Present/Absent:
    1. shorter to type - I type them a lot and the reason why the current syntax is bothersome to me is mostly because it's a lot of chars
    2. they are already used in other langs (Rust, Scala, probably others), so more familiar to their userbase (which I think massively overlaps with our most-likely-to-be userbase)
  • Some/None vs some/none: I'd classify them as "constructors" instead of "keyword"; now, in Dhall we don't have prior cases of "constructors" that we can refer to (as there is just special syntax to construct all other built-in values), but constructors are usually capitalized (in any language I can think of), so Some/None feels right

Then I have a couple of questions on the PR itself:

  • Having to do a massive replacing for the protocol version string every time we add an AST constructor is a lot of work. Would it be possible to call the encoding function just encode and then say "we specify encode for the latest version X.Y", and then specify a version only when specifying the encoding for cases in any other version than the latest?
  • If we normalize to the new Some/None (which is good) would this mean that when caching hash-protected imports the old [ .. ] : Optional .. form will not be present anymore? (since IIRC we beta-normalize imports before writing them to the cache)

@ocharles
Copy link
Member

ocharles commented Sep 1, 2018 via email

@Gabriella439
Copy link
Contributor Author

@f-f: Yeah, I'm warming up to Some/None myself, so I think I'll stick with them

Having to do a massive replacing for the protocol version string every time we add an AST constructor is a lot of work. Would it be possible to call the encoding function just encode and then say "we specify encode for the latest version X.Y", and then specify a version only when specifying the encoding for cases in any other version than the latest?

Sure, I will just use encode for the latest version

If we normalize to the new Some/None (which is good) would this mean that when caching hash-protected imports the old [ .. ] : Optional .. form will not be present anymore? (since IIRC we beta-normalize imports before writing them to the cache)

Yes. New cached values will now store Some/None for Optional literals. However, the binary protocol still has to specify how to serialize values that aren't in normal form (such as the legacy syntax for Optional literals) because binary serialization can be used for purposes other than caching (like transmitting Dhall expressions over the wire).

@istathar
Copy link

istathar commented Sep 2, 2018

Much as I'm not thrilled about Just (although Nothing is terrific!) for the optional type, the other FP convention of Some seems worse. In English, anyway, you don't have "some apple" or "none [apple]"; the word some goes with a quantity more than one.

Too bad There'sASingle and EmptinessOfTheVoid doesn't have the brevity and pizzazz we are looking for.

AfC

@Gabriella439 Gabriella439 merged commit ebf3d5a into master Sep 7, 2018
@Gabriella439 Gabriella439 deleted the gabriel/some_none branch September 7, 2018 15:39
Gabriella439 added a commit to dhall-lang/dhall-haskell that referenced this pull request Sep 10, 2018
... as standardized in dhall-lang/dhall-lang#227

The legacy `Optional` syntax is still supported for now but the normal form for `Optional`
literals now prefers `Some`/`None`.

The `dhall lint` command will automatically migrate the old `Optional` literal syntax to the
new syntax.
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.

None yet

6 participants