How can a function return dynamic data type

There is no way to choose a different type according to a different argument value. However, you can select an arbitrary type depending on the argument type.

To illustrate, let’s break down how you’re using Int in funcTest into a data type that represents only your possible arguments.

data N = One | Two | Other

And you would have a One, Two, and Other case in funcTest. However, this isn’t good enough to satisfy the rule I mentioned above.

However, consider another way of looking at the argument set to funcTest.

data One = One
data Two = Two
data Other = Other

Now I have types for the different arguments rather than just values. These I can relate to the desired return types as follows.

-- the first n -> z means "z depends on n";
--     it is solely about type variables
-- the second n -> z is the type of funcTest
class FuncTest n z | n -> z where
  funcTest : n -> z

-- I've skipped your DataType1 et al because I can just use
-- whatever result types I want

instance FuncTest One Int where
  funcTest One = 5

instance FuncTest Two Text where
  funcTest Two = "hello"

instance FuncTest Other Decimal where
  funcTest Other = 20.3

testFuncTest = script do
  -- these equality tests all pass and are well-typed
  funcTest One === 5
  funcTest Two === "hello"
  funcTest Other === 20.3
  {- does not compile, due to type error
  error:
    • Couldn't match type ‘Int’ with ‘Text’
        arising from a functional dependency between:
          constraint ‘FuncTest One Text’ arising from a use of ‘funcTest’
          instance ‘FuncTest One Int’ -}
  -- funcTest One === "hello"

This technique is an important part of the core operations of Daml. For example, exercise selects a return type depending on the contract type and choice type. It is not restricted to this order of determination, either: a result type can determine an argument type instead of the other way around. Or they can both determine each other.

I emphasize that an instance is selected at compile time. However, unlike with overloads, you can write your functions in such a way that “pass along” the FuncTest constraint and are thus polymorphic at compile-time themselves. createAndExercise is such a function. You might be interested in this forum post for more on class and instance:

2 Likes