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

DAML-LF: GenMap Spec #4981

Merged
merged 4 commits into from
Mar 16, 2020
Merged

DAML-LF: GenMap Spec #4981

merged 4 commits into from
Mar 16, 2020

Conversation

remyhaemmerle-da
Copy link
Collaborator

In this PR we specify the operational semantics of GenMap builtin.

This advance the state of #2256

Pull Request Checklist

  • Read and understand the contribution guidelines
  • Include appropriate tests
  • Set a descriptive title and thorough description
  • Add a reference to the issue this PR will solve, if appropriate
  • Include changelog additions in one or more commit message bodies between the CHANGELOG_BEGIN and CHANGELOG_END tags
  • Normal production system change, include purpose of change in description

NOTE: CI is not automatically run on non-members pull-requests for security
reasons. The reviewer will have to comment with /AzurePipelines run to
trigger the build.

daml-lf/spec/daml-lf-1.rst Outdated Show resolved Hide resolved
daml-lf/spec/daml-lf-1.rst Outdated Show resolved Hide resolved
daml-lf/spec/daml-lf-1.rst Outdated Show resolved Hide resolved
daml-lf/spec/daml-lf-1.rst Outdated Show resolved Hide resolved
value is replaced with the supplied value, otherwise the key/value
is inserted in order according the builtin function ``LESS`` applied
on keys. This raises a runtime error if it tries to compare
incomparable values.
Copy link

Choose a reason for hiding this comment

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

One question that the spec should answer: does it raise a runtime error when inserting a value that is incomparable in an empty map? (I think it should raise an error, for the sake of consistency.)

Copy link
Collaborator Author

@remyhaemmerle-da remyhaemmerle-da Mar 13, 2020

Choose a reason for hiding this comment

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

It does not.
It raise an exception exactly once LESS or EQUAL does.

We agreed with @hurryabit and @hurryabit that is the only semantics that is reasonable. Otherwise you will have to always traverse all the keys to ensure there is no function nested inside.

Imagine you have the type

data D = 
    FUN (Int -> Int) 
  | INT Int

You can insert (Fun (\x -> x)) in any GenMap that does not content Fun variant.
You can also try to lookup the entry of key (Fun (\x -> x)) without raising an exception in any GenMap that does not content Fun variant.

However as soon you have an entry with a key (Fun ...) in your map you cannot do anymore any operation that invole a other key of the form (Fun ...) without raising an exception.

This choices is simpler and more efficient. Furthermore the compiler will never produce such case.

Copy link

@ghost ghost Mar 13, 2020

Choose a reason for hiding this comment

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

Ok, if @hurryabit and @hurryabit can confirm ;-)

The reason I don't like this is that you are creating the potential for latent runtime errors when you perform inserts -- i.e. creating a runtime error that will only be found on a subsequent lookup, instead of when the real error occurs. This is particularly bad for e.g. people using genmaps during testing, or choice validation.

When adding a new key to the map, It should be easy to compare a key to itself using EQUAL, to make sure it doesn't introduce latent runtime errors.

Copy link

Choose a reason for hiding this comment

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

In the proposed semantics, you are only saving 1 comparison, but you are introducing latent runtime errors, so I don't think it's worth it.

Copy link
Contributor

Choose a reason for hiding this comment

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

It depends on what kind of values you have. If you have ADT-like trees, being able to short circuit on comparisons can make a pretty large difference. Given that we prevent this runtime error in DAML, I’m not sure that missing out on better performance here in favor of “nicer semantics” for DAML-LF is worth it. That said, I don’t feel particularly strongly about this.

Copy link
Collaborator Author

@remyhaemmerle-da remyhaemmerle-da Mar 13, 2020

Choose a reason for hiding this comment

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

In fact, @associahedron I like your proposal.
The advantage I see, is that we can switch the implementation to hashmap, if we realize the implementation is too slow (we will sorted the map only for serialization).

In other words, in each case (insertion, deletion and lookup) we check the value is equal to itself. Hence we have a nice definition of "comparable" value.

Copy link

Choose a reason for hiding this comment

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

@cocreature If you use nested trees as keys, maps are going to be slow regardless. I'm also not confident that this case will never ever occur at runtime in DAML.

@remyhaemmerle-da 👍

Copy link
Contributor

Choose a reason for hiding this comment

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

Alright, then let’s error out for now.


Looks up the value at a key in the map using the builtin function
``EQUAL`` to test key equality. This raises a runtime error if it
try to compare incomparable values.
Copy link

Choose a reason for hiding this comment

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

Spec should say what happens in the case of empty map lookup of incomparable keys. (I favor more runtime errors.)

Copy link

Choose a reason for hiding this comment

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

At lookup it is not super critical to check the key for self-equality, but I think that at insertion time it is more important.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

no error ;)

Copy link

Choose a reason for hiding this comment

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

if you want to leave the possibility for hashtable-based implementation open, you should error on bad lookup keys

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

As agreed in previous thread, we raise an error

daml-lf/spec/daml-lf-1.rst Outdated Show resolved Hide resolved
daml-lf/spec/daml-lf-1.rst Outdated Show resolved Hide resolved
daml-lf/spec/daml-lf-1.rst Outdated Show resolved Hide resolved
daml-lf/spec/daml-lf-1.rst Outdated Show resolved Hide resolved
Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

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

Thanks! This spec looks good, but we need to be explicit about what happens with empty maps.

**Validity of Keys:** A key is valid if and only if it is equivalent
to itself according to the relation ``~ᵥ`` defined below. Attempts to
use an invalid key in the operations above always result in a runtime
error.
Copy link

Choose a reason for hiding this comment

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

You can simply reinstate this paragraph if you want to leave the possibility for hashtable-based implementation open (but use EQUAL instead of ~ᵥ).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

done

Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

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

Approving since the missing insert rule was added, and we've discussed about the merits of error-ing on incomparable keys (I leave the final decision to you).

remyhaemmerle-da and others added 3 commits March 16, 2020 12:28
CHANGELOG_BEGIN
CHANGELOG_END
Co-Authored-By: associahedron <231829+associahedron@users.noreply.github.com>
@remyhaemmerle-da
Copy link
Collaborator Author

Thanks @associahedron for this constructive discussion. I believe it is better now.

@remyhaemmerle-da remyhaemmerle-da merged commit 1c26f63 into master Mar 16, 2020
@remyhaemmerle-da remyhaemmerle-da deleted the genmap-2 branch March 16, 2020 12:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants