How can a function return dynamic data type

In the dynamic case (I emphasize again that you cannot determine types based on values), you can take advantage of the fact that (a×b×c×d) + (a×b×c×e) + (a×b×c×f) = a×b×c×(d + e + f).

data DataTypeN = DataTypeN with
    firstName: Text
    lastName: Text
    age: Int
    specificTypeValue: STV

data STV = STV1 Int | STV2 Text | STV3 Decimal

data DataTypeOption = One | Two | Three

testFunc : DataTypeOption -> DataTypeN 
testFunc dataTypeOption = 
  DataTypeN with
    firstName = "Hello"
    lastName = "World"
    age = 16
    specificTypeValue = case dataTypeOption of
      One -> STV1 5
      Two -> STV2 "another test"
      Three -> STV3 20.0

Any set of fields in a record can always be refactored into a separate record type. See this forum post for many examples.

Meanwhile, in the type-to-type case I demonstrated in the previous example, you can perform the same factoring by using a type variable for specificTypeValue instead of the concrete STV sum type.

data DataTypeN stv = DataTypeN with
    firstName: Text
    lastName: Text
    age: Int
    specificTypeValue: stv

class FindSTV dto stv | dto -> stv where
  specificTypeValueOf : dto -> stv

data STV = STV1 Int | STV2 Text | STV3 Decimal

data One = One
data Two = Two
data Three = Three

testFunc : FindSTV dto stv => dto -> DataTypeN stv
testFunc dataTypeOption = 
  DataTypeN with
    firstName = "Hello"
    lastName = "World"
    age = 16
    specificTypeValue = specificTypeValueOf dataTypeOption

instance FindSTV One Int where
  specificTypeValueOf _ = 5

instance FindSTV Two Text where
  specificTypeValueOf _ = "another test"

instance FindSTV Three Decimal where
  specificTypeValueOf _ = 20.0

testTestFunc = script do
  [(testFunc One).age, (testFunc Two).age, (testFunc Three).age]
    === [16, 16, 16]
  (testFunc One).specificTypeValue === 5
  (testFunc Two).specificTypeValue === "another test"
  (testFunc Three).specificTypeValue === 20.0
  {- does not compile, due to type error
    • Couldn't match type ‘Int’ with ‘Text’
        arising from a functional dependency between:
          constraint ‘FindSTV One Text’ arising from a use of ‘testFunc’
          instance ‘FindSTV One Int’ -}
  -- (testFunc One).specificTypeValue === "hello"
1 Like