why doesn't the match version of the code compile, in F#

Viewed 69

here is some code:

type Test() =

    static member SomeValue =
        "AAA"

    static member test1 (a) =
        match a with
        | Test.SomeValue -> "a"
        | _              -> "b"

    static member test2 (a) =
        if a = Test.SomeValue then
            "a"
        else
            "b"

the test1 version will not compile ([FS0039] The type 'Test' does not define the field, constructor or member 'SomeValue'.) while test2 compiles.

Since SomeValue doesn't have any parameters, it will be evaluated once, making it a constant. Why doesn't the compiler accept it in that case?

2 Answers

In the test1 version you are using Pattern Matching thus you must provide a pattern after the pipe symbol (|).

But Test.SomeValue is a property, not a pattern, according to Microsoft document.

So, to use Pattern Matching in you code, for example, you can mark SomeValue as a Literal:

type Test() =

    [<Literal>] static let SomeValue = "AAA"

    static member test1 (a) =
        match a with
        | SomeValue -> "a"
        | _         -> "b"

    static member test2 (a) =
        if a = SomeValue then
            "a"
        else
            "b"

Above answer explains why you cannot match to a non build time constant. But if you cannot have that value as constant, then you are looking for a guard, which can operate on runtime values:

type Test() =

    static member SomeValue =
        "AAA"

    static member test1 (a) =
        match a with
        | x when x = Test.SomeValue -> "a"
        | _              -> "b"

    static member test2 (a) =
        if a = Test.SomeValue then
            "a"
        else
            "b"
Related