Skip to content

Allow upcasting in pattern match expressions #536

@chkn

Description

@chkn

Allow upcasting in pattern match expressions

I propose we enable some syntax to upcast a bound identifier in a pattern matching expression.

Consider this simple example:

type Base() = member __.SomeBaseMember = "hello"
type Foo() = inherit Base()
type Bar() = inherit Base()
type DU =
   | FOO of Foo
   | BAR of Bar
let foo = FOO(Foo())
match foo with
| FOO(b)
| BAR(b) -> b.SomeBaseMember

As expected, this code yields a message like:

This expression was expected to have type
     'Foo'    
 but here has type
     'Base'     at 5,6

I propose we add an upcast syntax so you can write something like:

match foo with
| FOO(b :> Base)
| BAR(b :> Base) -> b.SomeBaseMember

In the pattern match body, the identifier b would then be typed Base.

Alternatives

  1. Make no changes to the language and instead structure your code like this:

    match foo with
    | FOO(b) -> b.SomeBaseMember
    | BAR(b) -> b.SomeBaseMember

    This works, but when there are many cases, or when b.SomeBaseMember is actually a complex expression, this becomes less than ideal.

    A better workaround is to declare an active pattern:

    let inline (|Base|) b = b :> Base
    match foo with
     | FOO(Base b) 
     | BAR(Base b) -> b

    However, this is still not as elegant as an upcast operator built into the pattern matching language.

  2. Instead of adding new syntax, use the current type check pattern:

    match foo with
    | FOO(:? Base as b)
    | BAR(:? Base as b) -> b.SomeBaseMember

    This currently produces a compiler error:

Type constraint mismatch. The type 
     'Base'    
is not compatible with type
     'Foo'    
at 5,6

Pros and Cons

Pro: A more elegant syntax to solve the problem above.

Con: Requires implementation in the compiler

Extra informtion

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

Affadavit (must be submitted)

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 would be willing to help implement and/or test this
  • I or my company would be willing to help crowdfund F# Software Foundation members to work on this

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions