fslang-suggestions icon indicating copy to clipboard operation
fslang-suggestions copied to clipboard

Allow operators as active patterns

Open gusty opened this issue 4 years ago • 7 comments

Allow operators as active patterns

I propose we allow to define operators as active patterns, so we'll be able to write code like this:

match x with
| a ++ b -> ...

or

let (a ++ b) = x

This can be defined like let (| ++ |) x = ...

Pros and Cons

The advantages of making this adjustment to F# are:

  • More symmetry with operators used for construction.
  • Consistency with list pattern matching for list-like and tuple-like things.
  • More identifiers available for active patterns

The disadvantages of making this adjustment to F# are

  • Possible complications in updating F# parser

Extra information

Estimated cost XS / S:

Related suggestions: none that I know

Affidavit (please submit!)

Please tick this by placing a cross in the box:

  • [x] This is not a question (e.g. like one you might ask on stackoverflow) and I have searched stackoverflow for discussions of this issue
  • [x] I have searched both open and closed suggestions on this site and believe this is not a duplicate
  • [x] 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:

  • [x] This is not a breaking change to the F# language design
  • [x] 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 :+1: emoji on this issue. These counts are used to generally order the suggestions by engagement.

gusty avatar Apr 19 '21 06:04 gusty

What would happen to the existing pattern match operators |, & in that context?

7sharp9 avatar Apr 19 '21 08:04 7sharp9

@7sharp9 | is already not a valid custom operator, and & gives a warning that it shouldn't be used, so I guess it would be reasonable to forbid both of them as custom pattern operators.

Tarmil avatar Apr 19 '21 08:04 Tarmil

I meant during the match, as &/| are already allowed.

7sharp9 avatar Apr 19 '21 13:04 7sharp9

It is hard for me to comment without understanding more about code where you'd use it.

It would help me if you'd had samples of before/after added to the suggestion.

On the syntax, if the semantics are the same as active patterns, I suggest this:

let (|a ++ b|) = x

smoothdeveloper avatar Apr 22 '21 21:04 smoothdeveloper

Here are some cases where I miss this feature:

  • List-like user types:

If I define a NonEmptyList<'t> and an operator, like ++ to concatenate a head and a tail, to do the opposite I need to define a named active pattern, like (Cons (x, xs)), but it would be nice to use the same operator for both operations.

let nlist = head ++ tail
...
let (Cons (head, _)) = nlist

as opposed to

let (head ++ _) = nlist
  • Codecs: A codec type can be constructed from an encoding function and a decoding function. I use the <-> operator for that which symbolizes a bidirectional function. Codecs can also be deconstructed into that pair of functions, unfortunately that operation should be more verbose and I should use a different name for that.
    let codec = decoder <-> encoder
    ...
    let (Codec (decoder, _)) = codec

as opposed to

    let (decoder <-> _) = codec

In both cases, having the possibility to use the same operator to deconstruct leads to an API more consistent and therefore easier to use, as we don't have to remember two operations.

Contrast it with the :: operation for lists and the , operations for tuples and try to imagine how our code would look like without these operators being able to be used for deconstruction.

gusty avatar Oct 27 '21 05:10 gusty

Interesting idea. I kind of like it 🙂. Not sure if I'd ever use it, but I can see the use here.

cartermp avatar Oct 27 '21 18:10 cartermp

I'm not in favour of extending the role of user-definable symbolic operators in the language like this, into pattern matching. Just use an active pattern. As part of this, I'd kind of like to remove :: or make it type-directed.

dsyme avatar Oct 29 '21 10:10 dsyme