Cyclic dependencies, with an example

I am trying to create a simple example to illustrate the guidance in the old topic, Cyclic dependencies.

What if I start with a PingPong module, like this:

PingPong.daml
module PingPong where

template Ping with
   party : Party
  where
    signatory party
    choice RespondWithPong : ContractId Pong
      controller party
      do create Pong with ..

template Pong
  with party : Party
  where
    signatory party
    choice RespondWithPing : ContractId Ping
      controller party
      do create Ping with ..

Let’s pretend the PingPong module is getting too big. We would like to break it into two pieces – a module for Pings and a module for Pongs.

Naively copy-and-pasting the two templates into new modules results in the Cyclic module dependency between Pings, Pongs error.

Pings.daml
module Pings where

import Pongs

template Ping with
   party : Party
  where
    signatory party
    choice RespondWithPong : ContractId Pong
      controller party
      do create Pong with ..
Pongs.daml
module Pongs where

import Pings

template Pong
  with party : Party
  where
    signatory party
    choice RespondWithPing : ContractId Ping
      controller party
      do create Ping with ..

For this contrived example, what would the Daml look like when applying @bernhard’s suggestion:

Hi @WallaceKelly,

I believe the example you created falls into the description the the first paragraph in @bernhard’s reply. Since the templates are too simple to be broken apart into multiple ones, I see no option here to resolve the dependency other than moving the two templates into the same module (as they were originally).

Thanks, @Mate_Varga, for taking a look with me.

The example is definitely simple and contrived. I was thinking about it over the weekend and the best I could come up with is this:

  • Ping and Pong templates no longer generate the responses, since they cannot know about each other. (These become the “upstream”)
  • Introduce new Pinging and Ponging templates to generate the responses. (These are the “downstream”).

I’d welcome a better example!

Ping.daml
module Ping where

template Ping with
   party : Party
  where
    signatory party
Pong.daml
module Pong where

template Pong with
   party : Party
  where
    signatory party
Pinging.daml
module Pinging where

import Ping
import Pong

template Pinging
  with party : Party
  where
    signatory party

    choice Create : ContractId Ping
      controller party
      do create Ping with ..

    choice Respond : ContractId Ping
      with pong : ContractId Pong
      controller party
      do
        archive pong
        create Ping with..
Ponging.daml
module Ponging where

import Ping
import Pong

template Ponging
  with party : Party
  where
    signatory party

    choice Create : ContractId Pong
      controller party
      do create Pong with..

    choice Respond : ContractId Pong
      with ping : ContractId Ping
      controller party
      do
        archive ping
        create Pong with..
Main.daml
module Main where

import Daml.Script
import Pinging
import Ponging

demo = script do
  party <- allocateParty "party"

  ping <- submit party $ createAndExerciseCmd (Pinging party) Pinging.Create
  pong <- submit party $ createAndExerciseCmd (Ponging party) Ponging.Respond with ..
  ping <- submit party $ createAndExerciseCmd (Pinging party) Pinging.Respond with ..

  pure ()