question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Variant constructor matching (w/o argument) differs depending on package structure

See original GitHub issue

When working with multiple DAML packages imported into one another, I found that variant constructors without arguments take a unit argument when imported from another package, but take no argument when used in the same package. The following example shows the problem:

Package 1 contains this module with a variant definition and a function f1 with a case match on the variant

module Package1File where

data AVariant = V1 Int
              | V2

f1 : AVariant -> Text
f1 x = case x of
         V1 i -> "V1"
         V2   -> "V2"

Package 2 contains a module which imports Package1File and contains an identical function f2:

module Package2File where

import Package1File -- from package 1

f2 : AVariant -> Text
f2 x = case x of
         V1 i -> "V1"
         V2 _ -> "V2"

Note that the match on V2 uses a _ for an uninteresting argument. This example code compiles when distributed into two packages, but f2 is incorrect when it resides inside the first package.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:10 (10 by maintainers)

github_iconTop GitHub Comments

2reactions
sofiafaro-dacommented, Sep 1, 2020

Maybe worthwhile to note: The change of arity of this constructor only happens when the original package is depended upon as a data dependency. When using a full dependency the constructor match and value without argument compiles fine.

Yes, this is expected. “dependencies” use GHC’s built-in mechanism (interface files) so you have all information from the original package, whereas “data-dependencies” go back from built DALF files, and try to provide a DAML interface to LF code by adding stubs. It is at best an approximation of the original interface, and should, at this point, be thought of as something similar to using the ledger API or language bindings.

Ok, so, after looking into this and talking with @remyhaemmerle-da, it looks like we could change the way we’re compiling variants, so that “variant constructors of no input” end up as synthetic variant-record constructors where the record has no fields. We should gate this change by LF version at least, since it’s going to affect people who currently use data-dependencies or the ledger api.

I’ve been implementing this and it looks like a bigger change than I thought, and wouldn’t be surprised if it broke a lot of existing code. I would be a lot more comfortable with my first proposed solution – to change the default way of translating DAML-LF variants with unit constructors back into DAML types, so that you get a constructor with no argument instead of a constructor with a unit argument. We could even deprecate variant constructor with unit arguments from DAML, since they have dubious utility, like we did for record types whose constructor name doesn’t match the type name (because it doesn’t have a representation at the LF level).

cc @hurryabit

0reactions
hurryabitcommented, Sep 2, 2020

I agree with the suggestion to deprecate variant constructors with a single unnamed argument of type (). I would start by showing a warning that explains how you’ll get in trouble when using this with data-dependencies and what to use instead.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Variants - Cornell Computer Science
What's different than before is that those constructors carry additional data ... of when pattern matching against variants is what *Real World OCaml*...
Read more >
initializer_list constructor somehow excluded from std::variant ...
What it has, is a constructor template that accepts any type, T . But for that template to be chosen, the compiler has...
Read more >
How To Use std::visit With Multiple Variants and Parameters
We have a variant ( std::variant ) that represents a package with four various types, and then we use the VisitPackage structure to...
Read more >
(PDF) Typing deep pattern-matching in presence of polymorphic ...
By their very nature, polymorphic variants depend on pattern- matching to analyze their contents. However, only typing for shallow pattern-matching was ...
Read more >
method overloading in java example - elevateindy.org
Example 1: Overloading Parameter data types differ Example 2: Overloading ... cant find an exact match of invoked method (based on the argument...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found