Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Checked arithmetic operators #1035

Open
5 tasks done
Happypig375 opened this issue Jun 15, 2021 · 6 comments
Open
5 tasks done

Checked arithmetic operators #1035

Happypig375 opened this issue Jun 15, 2021 · 6 comments

Comments

@Happypig375
Copy link
Contributor

Checked arithmetic operators

The C# team is considering to add checked operators: static T checked operator +(T lhs, T rhs); which will be preferred in checked contexts, and only consider the regular (infer checkedness from compiler switch) operator if the signature of the checked operator does not fit. In contrast, when not in a checked context, checked operators will be ignored.

Although F# reserves checked as a keyword, my guess is that as with event and sealed, attributes will be used.

open System
type C =
    { c : int }
    static member (+) ({ c = x }, { c = y }) = x + y
    [<Checked>]
    static member (+) ({ c = x }, { c = y }) = Checked.(+) x y

With #96:

open System
type C =
    { c : int }
    static member (+) ({ c = x }, { c = y }) = x + y
    [<Checked>]
    static member (+) ({ c = x }, { c = y }) =
        open Checked
        x + y

This will emit op_Addition and op_AdditionChecked. If a checked operator is defined without the regular (infer checkedness from compiler switch) equivalent, an error will be raised.

C# will imply a checked scope inside implementations of checked arithmetic operators. Not sure if F# should follow.

The existing way of approaching this problem in F# is to write op_AdditionChecked directly that can only be used in C# once implemented in their end but being forced to write op_AdditionChecked when using from F#.

Whether allowing explicit unchecked operators is still unresolved from the C# side.

Pros and Cons

The advantages of making this adjustment to F# are

There is no way for a user to declare a type and support both checked and unchecked versions of an operator. This will make it hard to port various algorithms to use the proposed generic math interfaces exposed by the libraries team. Likewise, this makes it impossible to expose a type such as Int128 or UInt128 without the language simultaneously shipping its own support to avoid breaking changes.

The disadvantages of making this adjustment to F# are

This adds additional complexity to the language and allows users to introduce more kinds of breaking changes to their types.

Extra information

Estimated cost (XS, S, M, L, XL, XXL): S

Related suggestions: dotnet/csharplang#4665 - the linked C# issue

Affidavit (please submit!)

Please tick this by placing a cross in the box:

  • This is not a question (e.g. like one you might ask on stackoverflow) and I have searched stackoverflow for discussions of this issue
  • I have searched both open and closed suggestions on this site and believe this is not a duplicate
  • This is not something which has obviously "already been decided" in previous versions of F#. If you're questioning a fundamental design decision that has obviously already been taken (e.g. "Make F# untyped") then please don't submit it.

Please tick all that apply:

  • This is not a breaking change to the F# language design
  • I or my company would be willing to help implement and/or test this

For Readers

If you would like to see this issue implemented, please click the 👍 emoji on this issue. These counts are used to generally order the suggestions by engagement.

@charlesroddie
Copy link

Suggest closing to reduce the number of open issues in fslang-suggestions and reopening when the C# feature this is dependent on is confirmed.

@Happypig375
Copy link
Contributor Author

Oh obviously #179 should be closed too. It must await C# alignment.

@Happypig375
Copy link
Contributor Author

@charlesroddie And as you can see, the number of open issues is not a concern.
#807 (comment)
#610 (comment)
#608 (comment)
#875 (comment)

@dsyme
Copy link
Collaborator

dsyme commented Jun 16, 2021

I'm happy to have all these issues being tracked. It's good to go over things with a fine toothcomb :)

@dsyme
Copy link
Collaborator

dsyme commented Oct 28, 2022

I'd like to make progress on this issue now the dust is settling on .NET 7

@dsyme
Copy link
Collaborator

dsyme commented Oct 28, 2022

For definition of these operators, @Happypig375's suggestion of using an attribute is reasonable.

open System
type C =
    { c : int }
    static member (+) ({ c = x }, { c = y }) = x + y
    [<Checked>]
    static member (+) ({ c = x }, { c = y }) = Checked.(+) x y

Or we could ask people to use the name:

open System
type C =
    { c : int }
    static member (+) ({ c = x }, { c = y }) = x + y
    static member op_CheckedAddition ({ c = x }, { c = y }) = Checked.(+) x y

I'm actually not too fussed about asking people to use the explicit form.

There is a seperate difficult question about whether the definition of Checked.(+) is modified so that it uses a special SRTP constraint where op_CheckedAddition is used if it is present on a type, and op_Addition otherwise (this is for user-defined types).

Currently this is not done and it would technically be a breaking change to start doing it. However arguably it would always be the "right" thing to do and there are almost no types with op_CheckedAddition in existence today. Given the relatively low use of open Checked in F# code I think this is the right thing to do, under a language version switch

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants