Reputation: 5289
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
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