문제

So I have the following code which is giving a type mismatch compiler error, and I don't know why:

[<Test>]
member this.TheTest() =
    let tuple = (DateTime.Now, 10)
    let listOfTuples = [ tuple ]
    SomeType.SomeFunc(listOfTuples)

static member SomeFunc (listOfTuples: IEnumerable<Tuple<DateTime,int>>) =
    Console.WriteLine("foo")

Why are the types not compatible?

And more importantly, how can I express SomeFunc's signature to be compatible with the call?

도움이 되었습니까?

해결책

The actual issue here is trying to pass ('a * 'b) into a function taking Tuple<'a, 'b>. While the internal representation of these are the same, the F# compiler treats the two differently.

This is spelled out in the F# language spec, section 6.3.2:

When considered as static types, tuple types are distinct from their encoded form. However, the encoded form of tuple values and types is visible in the F# type system through runtime types.

The issue is that the compiler is using the "static types" to see if this function is a match, and according to the spec, it isn't.

And more importantly, how can I express SomeFunc's signature to be compatible with the call?

You can work around this in various ways. The simplest is to redefine the type specifications on your method to use tuple expressions as well:

static member SomeFunc (listOfTuples: IEnumerable<(DateTime * int)>) =
    Console.WriteLine("foo")

Note that the above can be written in a more idiomatic manner (with the exact same meaning) as:

static member SomeFunc (listOfTuples: (DateTime * int) seq) =
    Console.WriteLine("foo")
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top