Does DAML has something similar to type overloading?

Hello, I am new to Haskell / DAML, and have a basic question.

Below is some psuedo code which illustrates what I want to achieve… i.e. I want some kind of overloading which allow a single template to support different product catelogue. Would you please shred me some light on how can I achieve it in DAML?

Many thanks in advance!

data ComAProductCode = A1 | A2 | A3 deriving (Eq,Show)
data ComBProductCode = B1 | B2 | B3 deriving (Eq,Show)

data PurchaseOrderForComAorComB a = PurchaseOrderForComAorComB with
    code : a
    quantity : Int
deriving (Eq,Show)

template PurchaseOrderRequest 
    with
        buyer: Party
        seller: Party
        PurchaseOrderForComAorComB : PurchaseOrderForComAorComB a
    where
        signatory buyer
        observer seller
        controller buyer can
            nonconsuming Create: ContractId PurchaseOrderRequest
                with
                    purchaseOrder: PurchaseOrderFromComAorComB
                do
3 Likes

Hi @a14843, welcome to the forum! DAML currently doesn’t support type parameters at the template level so you have a few options:

  1. Declare a ProductCode variant type that covers both A and B: data ProductCode = PCComA ComAProductCode | PCComB ComBProductCode.
    You can then replace your parameter a with ProductCode. The downside of this approach is that ProductCode is a static list. Ie if a company C joins, you can’t easily extend this.
  2. Define a template per company: template PurchaseOrderRequestComA and template PurchaseOrderRequestComB. This has the obvious downside that consumers of PurchanseOrderRequest also need to be replicated per company.
  3. Type your product code weakly. Ie store it as a Text, not an enum.
2 Likes

It is also worth noting that this restriction only applies to Templates. The rest of your DAML code can use PurchaseOrderForComAorComB just fine. It’s only when writing data to the ledger that DAML currently needs to know the precise concrete type for its data.

So generally we use option 1 from @bernhard’s answer above in the template itself, and then either use that sum type for all the code, or define a function to convert it to the generic form in any choice that needs to use it.

1 Like

Some more help needed. I tried this:

data ComAProductCode = A1 | A2 | A3
deriving(Eq, Show)

data ComBProductCode = B1 | B2 | B3
deriving(Eq, Show)

data AllProductCode = PCComA ComAProductCode | PCComB ComBProductCode
deriving(Eq, Show)

Somewhere inside a template, I refer it:

    controller receipent can
        PurchaseOrderRequest_Accept: ContractId Invoice
            do
                now <- getTime
                let 
                    costForInsurance : Optional Decimal = if 
                        purchaseOrder.shippingAgreement == CIF &&
                        purchaseOrder.productCode == A1
                        then Some 3.0 
                        else None

The line “purchaseOrder.productCode == A1” gives me an error:

• Couldn't match type ‘AllProductCode’ with ‘ComAProductCode’
    arising from a functional dependency between:
      constraint ‘DA.Internal.Record.HasField
                    "productCode" PurchaseOrder ComAProductCode’
        arising from a use of ‘DA.Internal.Record.getField’
      instance ‘DA.Internal.Record.HasField
                  "productCode" PurchaseOrder AllProductCode’
        at <no location info>
• In the first argument of ‘(==)’, namely
    ‘(DA.Internal.Record.getField @"productCode" purchaseOrder)’
  In the second argument of ‘(&&)’, namely
    ‘(DA.Internal.Record.getField @"productCode" purchaseOrder) == A1’
  In the expression:
    (DA.Internal.Record.getField @"shippingAgreement" purchaseOrder)
      == CIF
      && (DA.Internal.Record.getField @"productCode" purchaseOrder) == A1 typecheck

Try changing

purchaseOrder.productCode == A1

to

purchaseOrder.productCode == PCComA A1

A1 is of type ComAProductCode so you need to apply the constructor to get a PCComA.

1 Like

Thanks heap for coming to my recuse in a timely fashion! I can move on with my project now.