Write a For Loop in DAML

Hi, Sorry for Newbie question, but how do I write a loop in DAML

eg. In following code, I want to create QuoteRequest’s passing the element from the array quoteInfos for each

...
nonconsuming CreateQuoteRequest : ContractId QuoteRequest
        with 
          quoteInfos : [QuoteInfo]
        do 
-- For (element in quoteInfos)
--  create QuoteRequest with element

...

template QuoteRequest
  with 
    quoteInfo : QuoteInfo
  where 
...

thanks

3 Likes

In DAML, there is no builtin construct that corresponds to a for-loop. However, there is a standard library function for this:

forA : Applicative m => [a] -> (a -> m b) -> m [b]

In your case you can instantiate the type variables to get:

forA : [QuoteInfo] -> (QuoteInfo -> Update (ContractId QuoteRequest)) -> Update [ContractId QuoteRequest]

Using this you can implement your choice as follows:

-- Note that I changed the type to return a list of contract ids. If you
-- only want to return one you have to decide which one and
-- what you want to do if `quoteInfos` is empty.
nonconsuming CreateQuoteRequest : [ContractId QuoteRequest]
  with
    quoteInfos : [QuoteInfo]
  do forA quoteInfos (\quoteInfo -> create QuoteRequest with quoteInfo)

If you do not care about the result, you can also use forA_ (you have to import DA.Foldable for that).

forA_ : [a] -> (a -> f b) -> f ()

Now you might wonder how those library functions are implemented themselves. The answer is recursion! Any for loop can be translated into a recursive function. Let’s take your example above and translate it into a recursive function:

createQuoteRequests : [QuoteInfo] -> Update [ContractId QuoteRequest]
createQuoteRequests [] = pure [] -- no quote infos so nothing to do
createQuoteRequests (quoteInfo :: quoteInfos) = do
  -- at least one quote info, first create that
  quoteRequestId <- create QuoteRequest with quoteInfo
  -- then recursively call createQuoteRequests to handle the tail of the list.
  quoteRequestIds <- createQuoteRequests quoteInfos
  -- now combine the results
  return (quoteRequestId :: quoteRequestIds)

This solves your specific problem. However because certain patterns occur so frequently they are captured as higher order functions in the standard library and it is generally good practice to make use of them instead of writing your own recursive functions.

8 Likes

Thank you for the Quick response

3 Likes

This can be a worthy addition to @drsk’s DAML cheat sheet

3 Likes

https://docs.daml.com/cheat-sheet/

2 Likes