# How to write a return case statement for a 2-element tuple?

**URL:** <https://forum.canton.network/t/how-to-write-a-return-case-statement-for-a-2-element-tuple/753>\
**Category:** App Development\
**Tags:** daml\
**Created:** [June 29, 2020, 8:39pm UTC](https://forum.canton.network/t/how-to-write-a-return-case-statement-for-a-2-element-tuple/753 "2020-06-29T20:39:36Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Chris\_Rivers](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/chris_rivers/32/420_2.png) [@Chris\_Rivers](https://forum.canton.network/u/Chris_Rivers)\
**Post date:** [June 29, 2020, 8:39pm UTC](https://forum.canton.network/t/how-to-write-a-return-case-statement-for-a-2-element-tuple/753/1 "2020-06-29T20:39:36Z")

</div>

Hi there! I’d like to use a return-case statement. The top-level function `generateResetPeriods` fetches the `CalculationPeriod` from the `generateResetPeriodDates`, which in turn returns a `floatingRateDefinition`.

Current return statement with more code:

```
generateResetPeriods : (Fetch f) => CalculationPeriodDates -> Optional ResetDates -> f [CalculationPeriod]
generateResetPeriods cpds None = generateCalculationPeriods cpds
generateResetPeriods cpds (Some (checkResetDates cpds -> rds)) = do
  -- Roll out calculation periods and unadjusted reset dates
  cps <- generateCalculationPeriods cpds
  let rpDatesV = map generateResetPeriodDates cps

  -- Set reset and fixing dates
  let adj = get "resetDatesAdjustments" rds.resetDatesAdjustments
  let fixingOffset = get "fixingDates" rds.fixingDates
  let resetRelativeTo = fromOptional ResetRelativeToEnumCalculationPeriodStartDate rds.resetRelativeTo
  mapA (setResetDates resetRelativeTo fixingOffset adj) $ zip cps rpDatesV -- takes cps and reset periods and returns one list

  where
    -- multiple resets per period not supported yet
    generateResetPeriodDates : CalculationPeriod -> [(Date, Date)]
    generateResetPeriodDates cp = [(get "adjustedStartDate" cp.adjustedStartDate, get "adjustedEndDate" cp.adjustedEndDate)]

    setResetDates :
      (Fetch f)
      => ResetRelativeToEnum
      -> RelativeDateOffset --
      -> BusinessDayAdjustments --
      -> (CalculationPeriod, [(Date, Date)]) --
      -> f CalculationPeriod
    setResetDates resetRelativeTo fixingOffset adj (cp, rpDates) = do
      resetDates <-
        case resetRelativeTo of
          ResetRelativeToEnumCalculationPeriodStartDate -> mapA (adjustDate adj . fst) rpDates
          ResetRelativeToEnumCalculationPeriodEndDate -> mapA (adjustDate adj . snd) rpDates

      ros <- mapA generateRateObservation resetDates
      return $ cp { floatingRateDefinition = Some FloatingRateDefinition
                                                    { calculatedRate = None
                                                    , capRate = []
                                                    , floatingRateMultiplier = None
                                                    , floorRate = []
                                                    , rateObservation = ros
                                                    , spread = None
                                                    }}

      ...

```

* * *

Is this the right case statement for a 2-element tuple?:

```
generateResetPeriods : (Fetch f) => CalculationPeriodDates -> Optional ResetDates -> f [CalculationPeriod]
generateResetPeriods cpds None = generateCalculationPeriods cpds
generateResetPeriods cpds (Some (checkResetDates cpds -> rds)) = do
  
  ...

  where
    
    generateResetPeriodDates : CalculationPeriod -> [(Date, Date)]
    generateResetPeriodDates cp = [(get "adjustedStartDate" cp.adjustedStartDate, get "adjustedEndDate" cp.adjustedEndDate)]

    ...
     
      return $ case (cp.floatingRateDefinition, cp.otherRateDefinition) of
               (Some floating, None) ->
                    cp { floatingRateDefinition = Some FloatingRateDefinition
                                                    { calculatedRate = None
                                                    , capRate = []
                                                    , floatingRateMultiplier = None
                                                    , floorRate = []
                                                    , rateObservation = ros
                                                    , spread = None
                                                    }}
               (None, Some other) ->
                    cp { otherRateDefinition = Some OtherRateDefinition
                                                    { calculatedRate = None
                                                    , capRate = []
                                                    , floatingRateMultiplier = None
                                                    , floorRate = []
                                                    , rateObservation = ros
                                                    , spread = None
                                                    }}
```

---

<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, 2020, 6:32am UTC](https://forum.canton.network/t/how-to-write-a-return-case-statement-for-a-2-element-tuple/753/2 "2020-06-30T06:32:57Z")

</div>

Hi @Chris_Rivers, the `case` statement looks fine apart from the fact that you are not handling the case where both are `None` and both are `Some`. Are you seeing any issues?

Two other comments on your code snippet:

1. It looks like you already define the result of `generateResetPeriodDates` in the first line of its definition so I’m not sure what the `return` is supposed to belong to.
2. Note that `return` in DAML is not the same as the return statement in languages like Java. It is a function of type `Applicative f => a -> f a`. What it does depends on the `Applicative` instance. For lists, i.e. `f = []`, it wraps the argument in a singleton list. For `Update` it allows you to lift a pure expression into an `Update` action that when executed will return the result of evaluating that expression.

---

<div class="post-metadata">

**Author:** ![Chris\_Rivers](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/chris_rivers/32/420_2.png) [@Chris\_Rivers](https://forum.canton.network/u/Chris_Rivers)\
**Post date:** [June 30, 2020, 2:39pm UTC](https://forum.canton.network/t/how-to-write-a-return-case-statement-for-a-2-element-tuple/753/3 "2020-06-30T14:39:18Z")

</div>

Hi @cocreature, although I expect either a Some-None or None-Some case, the compiler complained (gave warning) about not having the cases you mentioned and I got this error too:

```
Scenario execution failed on commit at Test.Event:116:23:
  Aborted: /Applications/DEV/DAML/ex-cdm-swaps copy/daml/Org/Isda/Cdm/EventSpecificationModule/Impl/Contract/Payout/InterestRatePayout/Schedule/ResetDates.daml:(63,16)-(79,54): Non-exhaustive patterns in case

Stack trace:
- patError (Control.Exception.Base:36:1)
- generateResetPeriods (Org.Issa.Srm.EventSpecificationModule.Impl.Contract.Payout.InterestRatePayout.Schedule.ResetDates:63:16)
- generateResetPeriods (Org.Issa.Srm.EventSpecificationModule.Impl.Contract.Payout.InterestRatePayout.Schedule.ResetDates:63:7)
...

```

However, in the case of Some-Some, how to include both `floatingRateDefinition` and `otherRateDefinition` within the scope of `cp`?

For your first comment, I included additional code above for `generateResetPeriodDates` for background. The code works fine in test cases with a single return statement, but not so when using the `return` `case`.

---

<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, 2020, 2:55pm UTC](https://forum.canton.network/t/how-to-write-a-return-case-statement-for-a-2-element-tuple/753/4 "2020-06-30T14:55:08Z")

</div>

> [@Chris\_Rivers](#):
>
> However, in the case of Some-Some, how to include both `floatingRateDefinition` and `otherRateDefinition` within the scope of `cp` ?

Something like this

```haskell
case (cp.floatingRangeDefinition, cp.otherRateDefinition) of
  (Some floating, Some other) -> …

```

Then in `…` both `floating` and `other` are in scope.

As for your error, I’m sadly still unable to see what is going wrong even with the additional context.  
Do you get a compile-time error or a runtime error? Can you share the error message? It would also be super helpful if you have a standalone example to reproduce the error.

---

<div class="post-metadata">

**Author:** ![Chris\_Rivers](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/chris_rivers/32/420_2.png) [@Chris\_Rivers](https://forum.canton.network/u/Chris_Rivers)\
**Post date:** [June 30, 2020, 3:10pm UTC](https://forum.canton.network/t/how-to-write-a-return-case-statement-for-a-2-element-tuple/753/5 "2020-06-30T15:10:07Z")

</div>

For the `Some-Some`, I haven’t figured out the write syntax for include both records in `cp`:

```
         (Some floating, Some other) ->
            cp { floatingRateDefinition = Some FloatingRateDefinition
                                                { calculatedRate = None
                                                , capRate = []
                                                , floatingRateMultiplier = None
                                                , floorRate = []
                                                , rateObservation = ros
                                                , spread = None
                                            } 
                 otherRateDefinition = Some OtherRateDefinition
                                                { calculatedRate = None
                                                , capRate = []
                                                , floatingRateMultiplier = None
                                                , floorRate = []
                                                , rateObservation = ros
                                                , spread = None
                                            }}
```

---

<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, 2020, 3:12pm UTC](https://forum.canton.network/t/how-to-write-a-return-case-statement-for-a-2-element-tuple/753/6 "2020-06-30T15:12:31Z")

</div>

You either need to use `with`-syntax or a comma:  
1.

```haskell
cp with
  floatingRateDefinition = Some …
  otherRateDefinition = Some …

```

1. 

```haskell
cp { floatingRateDefinition = Some …,
     otherRateDefinition = Some …
    }

```

Note that if you want to do the same thing for one of them independent of whether the other is `Some` you are probably better off doing two independent pattern matches.

---

<div class="post-metadata">

**Author:** ![Chris\_Rivers](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/chris_rivers/32/420_2.png) [@Chris\_Rivers](https://forum.canton.network/u/Chris_Rivers)\
**Post date:** [June 30, 2020, 3:17pm UTC](https://forum.canton.network/t/how-to-write-a-return-case-statement-for-a-2-element-tuple/753/7 "2020-06-30T15:17:10Z")

</div>

My runtime error:

```
Scenario execution failed on commit at Test.Event:116:23:
  Aborted: /Applications/DEV/DAML/ex-cdm-swaps copy/daml/Org/Issa/Srm/EventSpecificationModule/Impl/Contract/Payout/InterestRatePayout/Schedule/ResetDates.daml:(63,16)-(79,54): Non-exhaustive patterns in case

Stack trace:
- patError (Control.Exception.Base:36:1)
- generateResetPeriods (Org.Isda.Cdm.EventSpecificationModule.Impl.Contract.Payout.InterestRatePayout.Schedule.ResetDates:63:16)
- generateResetPeriods (Org.Isda.Cdm.EventSpecificationModule.Impl.Contract.Payout.InterestRatePayout.Schedule.ResetDates:63:7)
- $$c$u003e$u003e$u003d (Org.Isda.Cdm.EventSpecificationModule.Types.ReferenceData.Fetch:49:34)
- $$c$u003e$u003e$u003d (Org.Isda.cdm.EventSpecificationModule.Types.ReferenceData.Fetch:48:23)
- $$c$u003e$u003e$u003d (Org.Isda.Cdm.EventSpecificationModule.Types.ReferenceData.Fetch:48:23)
- $$cfmap (Org.Isda.Cdm.EventSpecificationModule.Types.ReferenceData.Fetch:37:47)
- $$cfmap (Org.Isda.Cdm.EventSpecificationModule.Types.ReferenceData.Fetch:37:24)
- $$c$u003c$u002a$u003e (Org.Isda.Cdm.EventSpecificationModule.Types.ReferenceData.Fetch:42:47)
- $$c$u003c$u002a$u003e (Org.Isda.Cdm.EventSpecificationModule.Types.ReferenceData.Fetch:42:23)
- $$c$u003e$u003e$u003d (Org.Isda.Cdm.EventSpecificationModule.Types.ReferenceData.Fetch:48:23)
- $$c$u003e$u003e$u003d (Org.Isda.Cdm.EventSpecificationModule.Types.ReferenceData.Fetch:48:46)
- $$c$u003e$u003e$u003d (Org.Isda.Cdm.EventSpecificationModule.Types.ReferenceData.Fetch:48:23)
- $$c$u003e$u003e$u003d (Org.Isda.Cdm.EventSpecificationModule.Types.ReferenceData.Fetch:48:46)
- $$c$u003e$u003e$u003d (Org.Isda.Cdm.EventSpecificationModule.Types.ReferenceData.Fetch:48:23)
- $$cfmap (Org.Isda.Cdm.EventSpecificationModule.Types.ReferenceData.Fetch:37:47)
- $$cfmap (Org.Isda.Cdm.EventSpecificationModule.Types.ReferenceData.Fetch:37:24)
- $$c$u003c$u002a$u003e (Org.Isda.Cdm.EventSpecificationModule.Types.ReferenceData.Fetch:42:47)
- $$c$u003c$u002a$u003e (Org.Isda.Cdm.EventSpecificationModule.Types.ReferenceData.Fetch:42:23)
- $$cfmap (Org.Isda.Cdm.EventSpecificationModule.Types.ReferenceData.Fetch:37:47)
- $$cfmap (Org.Isda.Cdm.EventSpecificationModule.Types.ReferenceData.Fetch:37:24)
- $$c$u003e$u003e$u003d (Org.Isda.Cdm.EventSpecificationModule.Types.ReferenceData.Fetch:48:46)
- $$c$u003e$u003e$u003d (Org.Isda.Cdm.EventSpecificationModule.Types.ReferenceData.Fetch:48:23)
- $$cfmap (Org.Isda.Cdm.EventSpecificationModule.Types.ReferenceData.Fetch:37:47)
- $$cfmap (Org.Isda.Cdm.EventSpecificationModule.Types.ReferenceData.Fetch:37:24)
- buildDerivedEvents (Org.Isda.Cdm.EventSpecificationModule.EventBuilder.Derived:37:41)
- buildDerivedEvents (Org.Isda.Cdm.EventSpecificationModule.EventBuilder.Derived:37:1)
- flip (DA.Internal.Prelude:369:1)
- $$cfmap (DA.Internal.LF:129:33)
- $$cfmap (DA.Internal.LF:129:22)

Ledger time: 2018-09-24T00:00:00Z

Partial transaction:
  Failed exercise (DA.Internal.Prelude:365:26):
    exercise Trigger on #13:0 (Main.Workflow.DeriveEvents:DeriveEventsWorkflow)
    with
      ciCid = #5:2;
      fromDate = some 2019-03-01T;
      toDate = some 2019-03-26T;
      refData =
        (Main.ReferenceData:RefData with
           holidayCalendarCids = [#10:0]; observationCids = [#11:0]; novelCids = [#12:0])
  Sub-transactions:
     #1
     └─> fetch #5:2 (Main.Market.Contract:ContractInstance)
     
     #2
     └─> fetch #10:0 (Main.ReferenceData:HolidayCalendarInstance)
     
     #3
     └─> fetch #11:0 (Main.ReferenceData:ObservationInstance)
     
     #4
     └─> fetch #12:0 (Main.ReferenceData:NovelInstance)
```

---

<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, 2020, 3:20pm UTC](https://forum.canton.network/t/how-to-write-a-return-case-statement-for-a-2-element-tuple/753/8 "2020-06-30T15:20:36Z")

</div>

`patError` sounds like you forgot a case but hit it in your scenario. I would recommend to add even the cases that you think you might not hit and call something like `error "unexpected case 1"`, `error "unexpected case 2"`.

---

<div class="post-metadata">

**Author:** ![Chris\_Rivers](https://yyz2.discourse-cdn.com/flex034/user_avatar/forum.canton.network/chris_rivers/32/420_2.png) [@Chris\_Rivers](https://forum.canton.network/u/Chris_Rivers)\
**Post date:** [June 30, 2020, 3:24pm UTC](https://forum.canton.network/t/how-to-write-a-return-case-statement-for-a-2-element-tuple/753/9 "2020-06-30T15:24:50Z")

</div>

Ok thanks. I’ll reply back either with a solution or standalone example.
