Using Either to toggle between types based on data restrictions

I have a question about the use of ‘Either’ when I need to have the option to ‘toggle’ between different Types in the event that a signatory would want to have the same basic data available for a ‘result’ but may want to restrict some of that data with a Bool (see ‘restricted’ below in the template). Basically, the ‘RestrictedResult’ would just provide less data if it is ‘restricted’.

How would I select either type ‘Result’ vs. ‘RestrictedResult’ as what I am trying isn’t working.

template ApiCall 
  with 
    provider: Party 
    requester: Party 
    broker: Party 
    idService: Party
    entity: Text 
    entityId: Text
    restricted: Bool
    requested: Time

  where 
    signatory broker, requester, idService 
    observer provider

    choice Answer: ContractId EsgResult 
      with 
        result : Either Result RestrictedResult
        result = if (restricted = False) then do result: Result
          else result: RestrictedResult
      controller provider 
      do
        asOf <- getTime
        -- add result here
          create EsgResult with ..

Does this get you closer to your intention?

template ApiCall 
  with 
    provider: Party 
    requester: Party 
    broker: Party 
    idService: Party
    entity: Text 
    entityId: Text
    restricted: Bool
    requested: Time
  where 
    signatory broker, requester, idService 
    observer provider

    choice Answer: ContractId EsgResult 
      controller provider 
      do
        let result = if restricted
            then Right $ RestrictedResult with..
            else Left $ Result with..
        asOf <- getTime
        create EsgResult with ..
1 Like

@Stephen_Herzig
I hope you find the example provided by @WallaceKelly useful.
To add to @WallaceKelly’s response, one error to note in your code, which @WallaceKelly corrected, is that the value of the type Either must be either Right someValue or Left someOtherValue.
The other problem in your code is that, if you’d like to pass the value of the result variable as an argument to the Answer choice, then the logic that assigns the value to the result must be implemented outside of the Answer choice. In other words the if statement, where you choose the value of the result variable as either Right $ RestrictedResult with .. or Left $ Result with .. cannot be implemented inside the Answer choice. It must be implemented elsewhere.
Alternatively you can have the logic that assigns the value to the result inside the Answer choice, as in @WallaceKelly’s example. But then you cannot pass the value of the result as an argument to the Answer choice.

2 Likes

It’s important to note that Either Result RestrictedResult isn’t “toggling” between Result and RestrictedResult–it’s just a regular type like any other type. It doesn’t bypass the requirement that every expression has a single type, which is why

if (restricted = False) then do result: Result else result: RestrictedResult

doesn’t work, the if-expression can’t have the type Result and the type RestrictedResult.

In the standard library, Either is defined as a variant with two data constructors, Left and Right:

data Either a b = Left a | Right b

You can read this as “A value of type Either a b, is either a Left holding an a-value, or a Right holding a b-value”. Here both Left’s and Right’s have the same type, namely Either a b.

2 Likes

Thanks, all! Very helpful, and solved the issue.