How to properly return multiple data types and utilize them?

Hello all,

In the sample code given below, I have two templates. I try to return multiple types of record data in one (namely Main) template based on some conditions and utilize it in the other contract (namely Test) as an input. However, because data types do not match, as expected, I receive an error states that:

Couldn’t match type ‘DataChoice Type_A Type_B Type_C’ with ‘Type_A’ arising from a functional dependency between: constraint ‘HasExercise Main Switch Type_A’ arising from a use of ‘exerciseCmd’ instance ‘HasExercise Main Switch (DataChoice Type_A Type_B Type_C)’at

My question is, is there any way to bypass it? How can I return a record data type let’s say, “Type_A” and consume it as an input parameter within another template in which I simply specify the data type as “Type_A” but not a Sum type?

module Hey where
import Daml.Script

data DataChoice a b c = ChoiceA a | ChoiceB b | ChoiceC c

data Type_A = Type_A with
    sig: Party
 deriving(Eq, Show)

data Type_B = Type_B with
    sig: Party
 deriving(Eq, Show)

data Type_C = Type_C with
    sig: Party
 deriving(Eq, Show)

template Main with
    sig: Party
  where
    signatory sig
    controller sig can
      Switch : DataChoice (Type_A) (Type_B) (Type_C)
        with
          cond : Int
        do
          if cond == 0 then do
              let a = Type_A {sig = sig}
              return (ChoiceA a)
          else if cond == 1 then do
              let b = Type_B {sig = sig}
              return (ChoiceB b)
          else do
              let c = Type_C with {sig = sig}
              return (ChoiceC c)

template Test with
    sig: Party
    content: Type_A
  where
    signatory sig
    controller sig can
      TestMe : ()
        do
            assert (content.sig == sig)

test: Script ()
test = do
  alice <- allocateParty "Alice"
  mainContract <- submit alice $ do createCmd Main with sig = alice
  contractChoiceExercised <- submit alice $ do exerciseCmd mainContract Switch with cond = 1
  testContract <- submit alice $ do createCmd Test with sig = alice, content = contractChoiceExercised

  return ()

In my way of thinking, the “Main” template here, could return Type_A, Type_B, or Type_C depends on the condition. And there would be multiple/separate contracts that consume these types as an input parameter. The fact that I want every single contract to be independent of each other, therefore, I do not want them to share a common data type i.e Sum type named as “DataChoice” in the current example.

Thank you in advance for your time and help!

2 Likes

This is not possible; Daml supports only discriminated unions, i.e. sum types.

You can solve the specific error you’ve quoted by pattern-matching the specific constructor of the sum type you expect to be there:

  ChoiceA contractChoiceExercised <- 

if you are happy with the default error you get if the pattern doesn’t match here; if you want a friendlier error, use case to handle ChoiceB and ChoiceC.

That said, outside of directly defining choices, you have a little freedom in defining various flavors of polymorphism when working with functions. It’s not for nothing that create and exercise work on every contract and choice. It’s hard to say whether that would interest you based only on what’s written here, though.

3 Likes

I understood, thank you very much Stephen for the clear explanation as well as your time and interest.

2 Likes