Reputation: 249
I am trying to write a function in F# 3.0 that accepts a sequence of tuples and returns a Dictionary but I can't seem to get the syntax right. The goal is to pass in a sequence of tuples of type 'K*'V and create a Dictionary<'K,'V>. Although I have tried various permutations, I cannot get the compiler to accept my syntax, for example:
CreateDictionary<'K, 'V, 'T when 'K : equality and T : 'K*'V>(s : seq<'T>)
On the other hand, this declaration is accepted:
CreateDictionary<'K, 'V when 'K : equality>(s : seq< Tuple<'K,'V> >)
but when I try to call it by passing seq<'K*'V> the compiler complains at the call site that:
...the type seq is not compatible with the type seq>...
Which is confusing because I thought that F# tuples corresponded to System.Tuple<>. So, obviously I'm missing something here.
What is the best way to declare a generic method that accepts a sequence of tuples?
Upvotes: 3
Views: 1340
Reputation: 243126
You do not need to define a new generic type for the tuple type:
let CreateDictionary<'K, 'V when 'K : equality>(s : seq<'K*'V>) =
(...)
This is fine, because you just want to say that the argument is a sequence of key value pairs where the key supports equality. The sort of constraint that you were trying to write might be useful in some cases, but not here - try the following:
let CreateDictionary<'K, 'V, 'T when 'K : equality and 'T :> 'K*'V>(s : seq<'T>) =
(...)
This would be saying that you want a sequence of values of type 'T
where 'T
is some type that inherits from 'K * 'V
(aka Tuple<'K, 'V>
). But since the tuple type is sealed, the compiler will give you an error saying that this constraint is not useful.
But it could be useful in some cases - you could write a function that takes any type that implements the sequence interface:
let CreateDictionary<'K, 'V, 'T when 'K : equality and 'T :> seq<'K*'V>>(s : 'T) =
(...)
This is not usually needed because F# will automatically convert lists, arrays, etc. to sequence when they are used as function arguments, but it is useful if you had e.g. a tuple containing any collection as a second argument.
EDIT And here is an example showing that the first function behaves as required:
[<NoEqualityAttribute;NoComparisonAttribute>]
type A() = class end
CreateDictionary [1,"hi"] // Compiles fine
CreateDictionary [A(),"hi"] // Error
Upvotes: 9