What's the recommended way to terminate early in an action, without failing?

For example, if I have a script and I want to run it to a given step (Int)?

I could have the full return type be an Either () () and include

if stopStep == 1
then pure $ Left ()
else do ..

Either or the transformer version EitherT (not in the standard library) are one of the better solutions for that atm. I wrote up an example of this a while back at ex-daml-error-handling/M2_UseAssert.daml at master · digital-asset/ex-daml-error-handling · GitHub. The biggest caveat if you are working in Update is that the actions you’ve taken are not rolled back which is often not what’s intended.

We are currently working on adding exception handling to DAML to make this a bit easier and allow for rollback. However if you are not in Update, then EitherT is probably still your best option.

You don’t have to indent do blocks to nest them so if you don’t need to return anything in the case where you don’t want continue, you can use the below pattern.

module Main where

import DA.Action

import Daml.Script

stepLimit = 3

stepwise : Script ()
stepwise = script do

  when (stepLimit >= 1) do
  debug "Step 1"

  when (stepLimit >= 2) do
  debug "Step 2"

  when (stepLimit >= 3) do
  debug "Step 3"

  when (stepLimit >= 4) do
  debug "Step 4"

  when (stepLimit >= 5) do
  debug "Step 5"

Or to make it prettyer:

module Main where

import DA.Action

import Daml.Script

stepWithLimit : (Action m) => Int -> Int -> m () -> m ()
stepWithLimit l n = when (l >= n)

stepwise : Script ()
stepwise = script do
  let step = stepWithLimit 3

  step 1 do
  debug "Step 1"

  step 2 do
  debug "Step 2"

  step 3 do
  debug "Step 3"

  step 4 do
  debug "Step 4"

  step 5 do
  debug "Step 5"
1 Like