Can a Choice in Daml conditionally return more than one type?

Choices are typically defined like:

    controller sig can
      Switch : ContractId TemplateA
        with
          cond : Int
        do

How would I return TemplateA OR TemplateB?

I could use a sum type, or the built-in type Either (if I only had two things to return), as below:

The one caveat with using Either is that it’s commonly understood that Left is treated as an error and Right is treated as a success. This doesn’t need to be the case and isn’t enforced by the type but is a fairly common construct.

module SumTypes where
import Daml.Script

-- Sum Type
data TemplateChoice a b c = ChoiceA a | ChoiceB b | ChoiceC c

template TemplateA with
    sig: Party
  where
    signatory sig

template TemplateB with
    sig: Party
  where
    signatory sig

template TemplateC with
    sig: Party
  where
    signatory sig

template Test with
    sig: Party
  where
    signatory sig
    controller sig can
      Switch : TemplateChoice (ContractId TemplateA) (ContractId TemplateB) (ContractId TemplateC)
        with
          cond : Int
        do
          case cond of
            0 -> do 
              a <- create TemplateA with ..
              return (ChoiceA a)
            1 -> do
              b <- create TemplateB with ..
              return (ChoiceB b)
            _ -> do
              c <- create TemplateC with ..
              return (ChoiceC c)

test: Script ()
test = do
  alice <- allocateParty "Alice"
  testContract <- submit alice $ do createCmd Test with sig = alice
  contractChoiceExercised <- submit alice $ do exerciseCmd testContract Switch with cond = 1
  return ()
  
  
--------- The Either version of the above:

template TestEither with
    sig: Party
  where
    signatory sig
    controller sig can
      TestEither_Switch : Either (ContractId TemplateA) (ContractId TemplateB)
        with
          cond : Bool
        do
          if cond
            then do
              a <- create TemplateA with ..
              return (Left a)
            else do
              b <- create TemplateB with ..
              return (Right b)
1 Like