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"