How to use the optionalToEither

G-d willing

Hello,
I am trying to use the optionalToEither but it seems I don’t understand it correctly.
I have the following code, which shows an error on the last line of code:

import DA.Either 

data Address = Address
  with
    apartmentNumber: Optional Int
    street: Text
    city: Text
    country: Text

setup : Script ()
setup = script do
  let 
    apartment = Apartment with number = Some 7
    street = "street name"
    city = "Tel Aviv"
    country = "Israel"
    apartmentNumber = optionalToEither "No Apartment" apartment.number

  let address = Address with apartmentNumber = fromRight apartment.number apartmentNumber, ..

The error that I am getting is:

c:/dev/daml/Hackathon/daml/Main.daml:31:48: error:
    • Couldn't match type ‘Optional Int’ with ‘Int’
        arising from a functional dependency between:
          constraint ‘DA.Internal.Record.HasField "number" Apartment Int’
            arising from a use of ‘getField’
          instance ‘DA.Internal.Record.HasField
                      "number" Apartment (Optional Int)’
            at <no location info>

I didn’t use strict Int in any place, so I need help in using it the right way?
Thanks

The issue is not in the call to optionalToEither but in the last line:

  1. After the call to optionalToEither, appartmentNumber has type Either String Int.
  2. Next, you’re calling fromRight appartment.number appartmentNumber.
  3. Let’s check the type of fromRight : b -> Either a b -> b. In your case, you have an Either String Int so b = Int. However, that means apartment.number must be of type Int but it is of type Optional Int and you get the error you are seeing.

I’m not quite sure what you are trying to set the field to so I have a hard time suggesting a fix. Maybe you just want to copy the previous value so apartmentNumber = aparment.number?

Why did you say “you have an `Either String Int”… why is it Int and not Optional Int?
apartment.number is defined as Optional Int

I wrote:

optionalToEither "No Apartment" apartment.number

“No Apartment” is String and “apartment.number” is defined as Optional Int.
So the optionalToEither is based on String and Optional Int.
How can I make the command to to return Either String Optional Int?

optionalToEither has type a -> Optional b -> Either a b. In your case, b = Int because you’re passing apartment.number : Optional Int. I don’t quite understand what you expect to get from an Either String (Optional Int). If apartment.number is None, do you expect to get back a Right None? If so, why do you need an Either at all?

Now I understood why it is Int and not Optional Int - please excuse me as I am still quite new with Daml and I am learning it through the work I need to complete.

The thing is that the project is using optionalToEithrt to validate their types and values… and I am supposed to assign them into data structures that will be saved into contracts.
So, while I cannot change the optionalToEither commands, I do need to assign them into Optional Int, and Optional Text fields.
What do you suggest me to do in this case?
I did try to use Some on top of fromRight, but this does not work as well

You could go the other way around with optionalToEither : Either a b -> Optional b. But at that point, I don’t really understand why you’re converting to an Either at all if you’re just going to turn it back into an Optional afterwards.

Maybe take a step back from the code and explain the underlying problem you are trying to solve?

I changed the code to the following:

let 
    apartment = Apartment with number = Some 7
    street = "street name"
    city = "Tel Aviv"
    country = "Israel"
    apartmentNumber = optionalToEither "No Apartment" apartment.number
    optAptNum = fromRight 0 apartmentNumber
    address = Address with apartmentNumber = optAptNum,..

And this does work, however, I don’t understand why.
Why optAptNum is defined as Optional Int

Can you share the definition of your Appartment and Address types?

G-d willing

Basically, it is a quite long story to explain, but I will try to do it shortly.
The first step in the project is simply reading data from an external source (XML files) which another team is validating in DAML - and they are outputting the results in case of errors - such as no apartment number and other data as well.
The next step is to assign only the correct values to the contracts’ data members.
So by the time I am getting the data, I am getting the values that were assigned by “optionalToEither”.
And I need to do the matching between these types to the real contract data members which are defined as Optional Int, Optional Text and etc…

Here you go…
This is not the original code as the real types are very long and complex, so this is an example to make it simple

data Apartment = Apartment
  with
    number: Optional Int
data Address = Address
  with
    apartmentNumber: Int
    street: Text
    city: Text
    country: Text

If you look at those definitions you can see that Address does not expect an Optional Int but an Int. So in your example above optAptNum = fromRight 0 apartmentNumber does have type Int not Optional Int and that’s why things typecheck. Note though that there is no point in going via Either here if you are going to throw away the text anyway, you can directly go for optAptNum = fromOptional 0 apartmentNumber (and probably change the variable name given that it’s an Int not an Optional Int).

G-d willing

Opps,
I forgot to change it, and I was sure it was defined as Optional Int. So now it is all clear to me.
Sometimes, after doing so many changes in code in order to “play” and understand things that I forgot to change it back, while thinking I already did it.
Thanks a lot @cocreature