Active template in F # 3.0

This active template 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 an error:

Active template '| Value | _ | ' has a result type that contains type variables that are not defined by the input. A common reason is [sic] when the case of the result is not mentioned, for example. 'let (| A | B |) (x: int) = A x'. This can be eliminated with a type restriction, for example. 'let (| A | B |) (x: int): Choice = A x'

I tried:

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

and

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

How can this be fixed?

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

EDIT: here's a simpler reprogramming:

 let (|X|) x = unbox x 
+8
f # visual-studio-2012 active-pattern
source share
4 answers

An error occurred in the F # 2.0 compiler when the compiler performed an incorrect analysis and generated incorrect code generation for certain active templates with free type variables as a result; simple reproduction

 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 strange warning at compile time and compiles into obviously incorrect code. I assume that our attempt to fix this error (and limit some crazy cases) in F # 3.0 also violated some legal code as a collateral damage to the fix.

I will write another error, but for F # 3.0, it seems you will need to use one of the workarounds mentioned in the other answers.

+4
source share

I have not installed the new version yet, but I agree that this looks a little suspicious. I suppose this restriction may be a good reason, but your example in another question seems rather complicated.

As a workaround, I think adding a witness parameter (which is not used, but hints what type of result will be) might work:

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

Of course, this makes use a little ugly because you need to come up with some kind of argument. In the above example, I used a witness like unit -> 'T , hoping that the following could compile:

 let witness () : 'T = failwith "!" match box 1 with | Value witness 1 -> printfn "one" 

If this does not work, you can probably try using a witness parameter of type 'T (but then you must provide the actual function, not just the generic function).

+3
source share

for completeness, another workaround:

 type Box<'R> = Box of obj let (|Value|_|) ((Box x) : Box<'R> ) : 'R option = match x with | :? 'R as x -> Some x | _ -> None let check t = match Box t with | Value 1 -> printfn "one" | Value 2 -> printfn "two" check 1 // one check 2 // two 

however, it will still suffer from the problem mentioned by @kvb in another thread . Personally, I would prefer the @kvb version with a parameterized active template.

+2
source share

See my answer to another question to find out how to work around the problem and one of the reasons that such active templates might be undesirable. I am not sure if the change has been changed.

0
source share

All Articles