I have a function with a signature like: myFuncA: Party -> MyTemplate -> Script (Optional (Commands ()))
which I use in daml test - the Idea is that returned command is later executed with submit or submitMustFail
I have also a trigger that uses (inside rule) a function myFuncB : Party -> MyTemplate -> TriggerA (Optional CommandId) (Optional (Command))
The point is that myFuncA and myFuncB have almost identical code (text of code - types are different) . Small Difference is that script uses queries like sth <- query @XX party
and trigger version sth <- query @XX
So far I could not reuse code.
Changing above function to a form: myFuncB : Action m => Party -> MyTemplate -> m (Optional (Command))
leads to compilation errors like:
Could not deduce (ActionTriggerAny m)
arising from a use of ‘query’
Instead of supplying ActionTriggerAny to unify parts of these three kinds of Action, we could have supplied three different query functions. In that case, it would still be possible for the user of the library to unify them with a typeclass like ActionTriggerAny.
Now, if it is possible to unify any part of two action APIs, why is it not done by the libraries themselves? Two reasons:
Structural: the libraries are considered independent; it is a major constraint to require them to conform to a common interface. Ironically, the unification I mentioned above would have been made more difficult or impossible were trigger committed previously to a separate interface.
Semantics: as @cocreaturementioned previously, superficial similarity can belie essential differences. query might look very similar, but that masks important differences in the way it interacts with command submission in the Script action API vs the TriggerA action API. Such differences can “poison” downstream code, seeming innocent in small test cases until they finally deliver unexpected results in the worst circumstances.
So, what does it mean when we put any possible unification in the hands of you, the trigger/script writer? It means that you are responsible for understanding how those semantic differences may affect your triggers’ and scripts’ behavior. However, once you accept that, you can express whatever the typeclass system lets you express, including, possibly, the unifying constraint you are looking for with respect to your triggers and scripts.