2

Given the following code...

type IMyInterface =
    abstract BoolA : bool
    abstract BoolB : bool
let myFn _boolVal (_i: IMyInterface) = if _boolVal then _i.BoolA else _i.BoolB
let myFnTrue = myFn true
let myFnFalse = myFn false

... Intellisense complains, and the compiler fails, if I create a signature file with this in it:

type IMyInterface =
    abstract BoolA : bool
    abstract BoolB : bool
val myFnTrue : (IMyInterface -> bool)
val myFnFalse : (IMyInterface -> bool)

The error is Error 10 Module 'MyModule' contains val myFnTrue : ('_a -> bool) when '_a :> MyModule.IMyInterface but its signature specifies val myFnTrue : (MyModule.IMyInterface -> bool) The types differ. (A similar error is reported for myFnFalse.)

I feel like an idiot, not being able to figure this out. What am I doing wrong? (Bracing for the "duh" answer...)

MiloDC
  • 2,373
  • 1
  • 16
  • 25

1 Answers1

2

In your signature file, myFnTrue and myFnFalse have the signature IMyInterface -> bool but in your implementation 'a -> bool with the constraint 'a :> IMyInterface (due to automatic generalization), that is, the implementation is generic and the signature is not.

The simplest solution is changing your implementation to this:

let myFnTrue i = myFn true i
let myFnFalse i = myFn false i
Daniel
  • 47,404
  • 11
  • 101
  • 179
  • I see. So although `myFn` specifies a typed argument, creating a function that takes an `IMyInterface` and returns a Boolean via `myFn true/false` results in a function with a generic first argument. This doesn't happen with other types (e.g. I tried it with int instead of an interface, no problem there), so what is it about interfaces that causes this? – MiloDC Feb 15 '13 at 21:56
  • 1
    It's not possible to generalize `int`: `'a :> int` is not a valid constraint. – Daniel Feb 15 '13 at 22:01