# Non aborting forA loop

**URL:** <https://forum.canton.network/t/non-aborting-fora-loop/2792>\
**Category:** App Development\
**Tags:** daml\
**Created:** [June 30, 2021, 10:40am UTC](https://forum.canton.network/t/non-aborting-fora-loop/2792 "2021-06-30T10:40:27Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Pris17](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/pris17/32/2078_2.png) [@Pris17](https://forum.canton.network/u/Pris17)\
**Post date:** [June 30, 2021, 10:40am UTC](https://forum.canton.network/t/non-aborting-fora-loop/2792/1 "2021-06-30T10:40:27Z")

</div>

I want to continue the execution of forA loop even after one of my case conditions is not satisfied. Below is my code snippet

```haskell
              dvdata <- forA otherparties (\dv -> do
                cID <- lookupByKey @ContractA (dv, id)
                case cID of
                  Some cId -> do
                    dvCon <- fetch cId                   
                    case partyToText dv of
                      "DV1" -> do
                        let sRDV1 = SRData 
                              with a = dvCon.abc
                                       b = dvCon.def
                        return (sRDV1)
                      "DV2" -> do
                        let sRDV2 = SRData 
                              with a = dvCon.abc
                                       b = dvCon.def
                        return (sRDV2)
                      _ -> error "No valid DV"
                  None -> return ()) --Here I want to continue the forA loop execution with next element

```

How do I achieve this?

---

<div class="post-metadata">

**Author:** ![cocreature](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/cocreature/32/36_2.png) [@cocreature](https://forum.canton.network/u/cocreature)\
**Post date:** [June 30, 2021, 10:40am UTC](https://forum.canton.network/t/non-aborting-fora-loop/2792/2 "2021-06-30T10:40:54Z")

</div>

What do you want to be returned for the case that currently calls `error`?

---

<div class="post-metadata">

**Author:** ![Pris17](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/pris17/32/2078_2.png) [@Pris17](https://forum.canton.network/u/Pris17)\
**Post date:** [June 30, 2021, 11:33am UTC](https://forum.canton.network/t/non-aborting-fora-loop/2792/3 "2021-06-30T11:33:45Z")

</div>

```haskell
None -> return ()) --Here I want to continue the forA loop execution with next element

```

@cocreature Here I want to continue with the next element of the forA loop and return nothing.

---

<div class="post-metadata">

**Author:** ![Gary\_Verhaegen](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/gary_verhaegen/32/81_2.png) [@Gary\_Verhaegen](https://forum.canton.network/u/Gary_Verhaegen)\
**Post date:** [June 30, 2021, 11:40am UTC](https://forum.canton.network/t/non-aborting-fora-loop/2792/4 "2021-06-30T11:40:24Z")

</div>

First off, and I can’t stress this enough: mentioning explicit party names in code is a very bad code smell in Daml. There are _very few_ cases where that is the right approach.

Ignoring that, as @cocreature said, if you don’t want your code to stop you have to return _something_. The simplest option is to wrap your return value in an `Optional` and return `None` for items you’d like to skip.

But first, let’s place your original snippet in a context where it actually compiles:

```haskell
module Main where

import Daml.Script

template ContractA
  with
    sig: Party
    id: Text
    abc: Text
    obs: Party
  where
    signatory sig
    observer obs
    key (sig, id) : (Party, Text)
    maintainer key._1

template ContractB
  with
    sig: Party
    collabData: [(Party, Text)]
  where
    signatory sig

data SRData = SRData with a: Text
  deriving Show

setup : Script ()
setup = script do
  party1 <- allocatePartyWithHint "DV1" (PartyIdHint "DV1")
  party2 <- allocatePartyWithHint "DV2" (PartyIdHint "DV2")
  mainParty <- allocatePartyWithHint "mainParty" (PartyIdHint "mainParty")

  submit party1 do
    createCmd ContractA with sig = party1, obs = mainParty, id = "keyData", abc = "some data"
  submit party2 do
    createCmd ContractA with sig = party2, obs = mainParty, id = "keyData", abc = "some other data"
  collect <- submitMulti [mainParty, party1, party2] [] do
    createCmd DoCollection with main = mainParty, others = [party1, party2]

  submit mainParty do
    exerciseCmd collect CreateContractB with parties = [party1, party2], id = "keyData"
  return ()

template DoCollection
  with
    main: Party
    others: [Party]
  where
    signatory main :: others
    nonconsuming choice CreateContractB : ()
      with parties: [Party]
           id: Text
      controller main
      do
        dvdata <- forA parties (\dv -> do
          cID <- lookupByKey @ContractA (dv, id)
          case cID of
            Some cId -> do
              dvCon <- fetch cId                   
              case partyToText dv of
                "DV1" -> do
                  let sRDV1 = SRData with a = dvCon.abc
                  return (sRDV1)
                "DV2" -> do
                  let sRDV2 = SRData with a = dvCon.abc
                  return (sRDV2)
                _ -> error "No valid DV"
            -- Note: can't return `()` here because that's the
            -- wrong type
            None -> error "original code errors here")
        debug dvdata

```

This prints:

```haskell
[SRData {a = "some data"},SRData {a = "some other data"}]

```

And the (inferred) type of `dvdata` is `[SRData]`.

I’ve removed the `def` part out of pure laziness; the main change is that the `None` case cannot return `()`, because there is no type that includes both `()` and the return values of the `Some` branch (`SRData`).

This is, in fact, the same problem you have with the `_` case.

Wrapping your return value in an `Optional` solves both:

```haskell
      do
        dvdata <- forA parties (\dv -> do
          cID <- lookupByKey @ContractA (dv, id)
          case cID of
            Some cId -> do
              dvCon <- fetch cId                   
              case partyToText dv of
                "DV1" -> do
                  let sRDV1 = SRData with a = dvCon.abc
                  return (Some sRDV1)
                "DV2" -> do
                  let sRDV2 = SRData with a = dvCon.abc
                  return (Some sRDV2)
                _ -> return None
            None -> return None)
        debug dvdata

```

which prints

```haskell
[Some (SRData {a = "some data"}),Some (SRData {a = "some other data"})]

```

where the inferred type of `dvdata` is now `[Optional SRData]`.

So what actually happens if we’re missing some data? You can try it; for example, removing the creation of `party1`'s contract, we now print:

```haskell
[None,Some (SRData {a = "some other data"})]

```

Similarly, adding a third party and creating a contract for them would yield:

```haskell
[Some (SRData {a = "some data"}),Some (SRData {a = "some other data"}),None]

```

And, if we _both_ don’t create the contract for `"DV1"` _and_ add a third party, we’d print:

```haskell
[None,Some (SRData {a = "some other data"}),None]

```

One issue with this is that we don’t know _why_ things fail. In this last list, the first `None` is because the contract was not found, whereas the second `None` was because the contract _was_ found but did not have the properties we wanted (wrong party in this case). Rather than returning a `Optional`, we could choose to return a `Either`. Whereas `Optional a` has two constructors `Some a` and `None`, where only `Some a` can have attached data, `Either a b` has two constructors `Left a` and `Right b`, both of which can have attached data (of potentially different types `a` and `b`).

Using this, we could return some explanation for the error:

```haskell
      do
        dvdata <- forA parties (\dv -> do
          cID <- lookupByKey @ContractA (dv, id)
          case cID of
            Some cId -> do
              dvCon <- fetch cId                   
              case partyToText dv of
                "DV1" -> do
                  let sRDV1 = SRData with a = dvCon.abc
                  return (Right sRDV1)
                "DV2" -> do
                  let sRDV2 = SRData with a = dvCon.abc
                  return (Right sRDV2)
                _ -> return (Left "wrong party")
            None -> return (Left "contract not found"))
        debug dvdata

```

which prints:

```haskell
[Left "contract not found",Right (SRData {a = "some other data"}),Left "wrong party"]

```

now of type `[Either Text SRData]`.

Finally, maybe you just don’t care about the errors and you just want a list of the contracts that _do_ match. You could write a filtering function yourself:

```haskell
filterEither : [Either a b] -> [b]
filterEither [] = []
filterEither (e::es) = case e of
  Left _ -> filterEither es
  Right a -> a :: filterEither es

```

or, in this case, use the builtin `DA.Either.rights`. For reference, here is the complete code again, this time using `Either` as the return type, skipping the contract creation for `"DV1"`, adding a `"DV3"`, and printing both the complete list with failures and the list of only the successes:

```haskell
module Main where

import Daml.Script
import qualified DA.Either

template ContractA
  with
    sig: Party
    id: Text
    abc: Text
    obs: Party
  where
    signatory sig
    observer obs
    key (sig, id) : (Party, Text)
    maintainer key._1

template ContractB
  with
    sig: Party
    collabData: [(Party, Text)]
  where
    signatory sig

data SRData = SRData with a: Text
  deriving Show

filterEither : [Either a b] -> [b]
filterEither [] = []
filterEither (e::es) = case e of
  Left _ -> filterEither es
  Right a -> a :: filterEither es

setup : Script ()
setup = script do
  party1 <- allocatePartyWithHint "DV1" (PartyIdHint "DV1")
  party2 <- allocatePartyWithHint "DV2" (PartyIdHint "DV2")
  party3 <- allocatePartyWithHint "DV3" (PartyIdHint "DV3")
  mainParty <- allocatePartyWithHint "mainParty" (PartyIdHint "mainParty")

  --submit party1 do
  -- createCmd ContractA with sig = party1, obs = mainParty, id = "keyData", abc = "some data"
  submit party2 do
    createCmd ContractA with sig = party2, obs = mainParty, id = "keyData", abc = "some other data"
  submit party3 do
    createCmd ContractA with sig = party3, obs = mainParty, id = "keyData", abc = "yet another data"

  let others = [party1, party2, party3]  
  collect <- submitMulti (mainParty :: others) [] do
    createCmd DoCollection with main = mainParty, ..

  submit mainParty do
    exerciseCmd collect CreateContractB with parties = others, id = "keyData"
  return ()

template DoCollection
  with
    main: Party
    others: [Party]
  where
    signatory main :: others
    nonconsuming choice CreateContractB : ()
      with parties: [Party]
           id: Text
      controller main
      do
        dvdata <- forA parties (\dv -> do
          cID <- lookupByKey @ContractA (dv, id)
          case cID of
            Some cId -> do
              dvCon <- fetch cId                   
              case partyToText dv of
                "DV1" -> do
                  let sRDV1 = SRData with a = dvCon.abc
                  return (Right sRDV1)
                "DV2" -> do
                  let sRDV2 = SRData with a = dvCon.abc
                  return (Right sRDV2)
                _ -> return (Left "wrong party")
            None -> return (Left "contract not found"))
        debug dvdata
        debug (filterEither dvdata)
        debug (DA.Either.rights dvdata)

```

---

<div class="post-metadata">

**Author:** ![Pris17](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/pris17/32/2078_2.png) [@Pris17](https://forum.canton.network/u/Pris17)\
**Post date:** [June 30, 2021, 2:02pm UTC](https://forum.canton.network/t/non-aborting-fora-loop/2792/5 "2021-06-30T14:02:47Z")

</div>

@Gary_Verhaegen Thanks for your reply. The code works as expected. I was trying to extract data from `DA.Either.rights dvdata` which is the list `[SRData {a = "some other data"}]` having type SRData. I am unable to fetch the value of a. Can’t we just use again forA to iterate over list and extract the value of a from each SRData object?

---

<div class="post-metadata">

**Author:** ![Pris17](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/pris17/32/2078_2.png) [@Pris17](https://forum.canton.network/u/Pris17)\
**Post date:** [June 30, 2021, 2:43pm UTC](https://forum.canton.network/t/non-aborting-fora-loop/2792/6 "2021-06-30T14:43:09Z")

</div>

Figured it out. Ignore my previous reply.

---

<div class="post-metadata">

**Author:** ![Gary\_Verhaegen](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/gary_verhaegen/32/81_2.png) [@Gary\_Verhaegen](https://forum.canton.network/u/Gary_Verhaegen)\
**Post date:** [June 30, 2021, 3:30pm UTC](https://forum.canton.network/t/non-aborting-fora-loop/2792/7 "2021-06-30T15:30:06Z")

</div>

Glad you figured it out! For the benefit of future readers who might ask themselves the same question, here is how I would have answered.

You should use `forA` when you want to execute some sequence of _ledger actions_ over a list. In the code above, we do a `lookupByKey` operation for each `Party` in the `parties` list.

If all you want is to extract data you already have from a list, you can apply a function to every element of the list using `map`, which is a bit like `forA` in that it will execute the function on each element of the list, but different in that it will not call out to the ledger.

So if you want to have a `[Text]` instead of a `[SRData]` (by extracting the `a` field, which is of type `Text`), you can do something like:

```haskell
map (\srdata -> srdata.a) list_of_srdata

```

Or, in the case where you have `[Either Text SRData]`, as we had in the last code example, you could go for:

```haskell
debug (map (.a) $ DA.Either.rights dvdata)

```

which would print

```haskell
["some other data"]

```

where `(.a)` is a shorthand notation for `(\x -> x.a) `.
