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!
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?
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.
I understood, thank you very much Stephen for the clear explanation as well as your time and interest.