Maurice Flanagan
Maurice Flanagan

Reputation: 5289

Confusing error using F# Active Pattern

Why does this compile:

let (|T|F|) b = 
    let f (o:int) : obj = null
    if b then T else F(f)

while this fails:

let (|T|F|) b = 
    let f (o:obj) : obj = null
    if b then T else F(f)

The difference between the two examples is the argument 'o' is coerced to either an 'int' (compiles) or an 'obj' (fails to compile)

Upvotes: 3

Views: 213

Answers (1)

kvb
kvb

Reputation: 55184

It's an unfortunate type inference corner case. This will work:

let (|T|F|) b : Choice<unit,obj -> obj> =   
  let f (o:obj) : obj = null
  if b then T else F(f)

In your original code, despite your annotation (o:obj), F# infers that o could actually be of any type 'a, which leads to a generic active pattern of type bool -> Choice<unit,'a -> obj>. Because 'a is a free type variable, F# won't accept this active pattern definition. You can see a similar problem if you do something like:

let (|T|F|) b =   
  if b then T else F []

Again, the solution would be to monomorphize the definition:

let (|T|F|) b : Choice<unit,int list>  =   
  if b then T else F []

Upvotes: 8

Related Questions