Search code examples
f#visual-studio-2012f#-3.0active-pattern

Active pattern broken in F# 3.0


This active pattern compiles with F# 2.0:

let (|Value|_|) value = // 'a -> 'T option
  match box value with
  | :? 'T as x -> Some x
  | _ -> None

but, in F# 3.0, emits the error:

Active pattern '|Value|_|' has a result type containing type variables that are not determined by the input. The common cause is a [sic] when a result case is not mentioned, e.g. 'let (|A|B|) (x:int) = A x'. This can be fixed with a type constraint, e.g. 'let (|A|B|) (x:int) : Choice = A x'

I tried:

let (|Value|_|) value : 'T option = ...

and:

let (|Value|_|) (value: 'U) = ...

How can it be fixed?

Environments: Visual Studio 2012 (RTM) and FSI v11.0.50727.1

EDIT: Here's a simpler repro:

let (|X|) x = unbox x

Solution

  • There was a bug in the F# 2.0 compiler where the compiler did incorrect analysis and bad code generation for certain Active Patterns with free type variables in the result; a simple repro is

    let (|Check|) (a : int) = a, None
    //let (|Check|) (a : int) = a, (None : int option)
    
    let check a = 
        match a with
        | Check (10, None) -> System.Console.WriteLine "10"
        | Check (20, None) -> System.Console.WriteLine "20"
    
    check 10
    check 20
    

    which generates a weird warning at compile-time and compiles into seemingly incorrect code. I am guessing that our attempt to fix this bug (and restrict some crazy cases) in F# 3.0 also broke some legal code as collateral damage of the fix.

    I'll file another bug, but for F# 3.0, it sounds like you'll need to use one of the workarounds mentioned in other answers.