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
                                                    }}
             
            
              
              
              1 Like
            
            
           
          
            
            
              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:
- It looks like you already define the result of generateResetPeriodDatesin the first line of its definition so I’m not sure what thereturnis supposed to belong to.
- Note that returnin DAML is not the same as the return statement in languages like Java. It is a function of typeApplicative f => a -> f a. What it does depends on theApplicativeinstance. For lists, i.e.f = [], it wraps the argument in a singleton list. ForUpdateit allows you to lift a pure expression into anUpdateaction that when executed will return the result of evaluating that expression.
 
            
              
              
              1 Like
            
            
           
          
            
            
              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.
             
            
              
              
              1 Like
            
            
           
          
            
            
              
Something like this
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.
             
            
              
              
              1 Like
            
            
           
          
            
            
              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
                                            }}
             
            
              
              
              1 Like
            
            
           
          
            
            
              You either need to use with-syntax or a comma:
1.
cp with
  floatingRateDefinition = Some …
  otherRateDefinition = Some …
- 
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.
             
            
              
              
              1 Like
            
            
           
          
            
            
              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)
             
            
              
              
              
            
            
           
          
            
            
              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".
             
            
              
              
              1 Like
            
            
           
          
            
            
              Ok thanks. I’ll reply back either with a solution or standalone example.
             
            
              
              
              1 Like