F# active pattern as non-static member

592 views Asked by At

I'm not sure if non-static public member active patterns are allowed but you can define them without the compiler complaining. If they are allowed what's the syntax for matching against one? The compiler is giving me a type mismatch for Foo in FooBar2.doSomething. Expecting a 'a -> Choice<'b,'c> given 'a -> 'd -> Choice<unit,unit>

// No error in this class, static works great
type FooBar() = 
    static member (|Foo|Bar|) (x, y) =
        match x = y with
        | true -> Foo
        | false -> Bar

    member x.doSomething y =
        match x, y with
        | Foo -> ()
        | Bar -> ()

type FooBar2() = 
    member x.(|Foo|Bar|) y =
        match x = y with
        | true -> Foo
        | false -> Bar

    // compiler error on "Foo"    
    member x.doSomething y =
        match y with
        | Foo -> ()
        | Bar -> ()
3

There are 3 answers

1
Brian On BEST ANSWER

Active patterns should not be used as members. The fact that these compile at all is a compiler bug that we'll fix (thanks for the report :) ). Use local or module-bound "let"s to define an active pattern.

0
kvb On

I'm not surprised that this doesn't work, and I can't see a natural semantic interpretation for instance active patterns. How do you know which instance to use when you see the Foo pattern? Could you have different instances for the Foo and Bar cases (and therefore an incomplete pattern match)? There doesn't seem to be an elegant resolution to the issues here. To be honest, I'm suprised that even the static case works, and I don't see anything in the spec addressing the definition of active patterns as members of any kind.

0
Thomas On

Member recognizers seem to be out since version 1.9.9.9. even for static members. I think it is a shame because it allowed for recognizer overloading. I could have a 'Name' recognizer for Type, MemberInfo etc. Now I need to have a 'Type_Name'. 'Member_Name' etc. to avoid naming conflicts. Just 'Name' was nicer.