Reputation: 155
When I try to add an item to a list like this:
open MongoDB.Driver
type SegmentId = string
type SegmentRM =
{ id : SegmentId
users: string list }
let addUserToSegment (collection : IMongoCollection<SegmentRM>) (id: SegmentId) (usr: string) =
let filter = Builders.Filter.Eq((fun x -> x.id), id)
let update = Builders.Update.Push<string>((fun x -> x.users), usr)
collection.UpdateOneAsync(filter, update)
I have a compilation error
No overloads match for method 'Push'. The available overloads are shown below.
And also tried with users: string[]
with the same error.
Anybody knows how to avoid this compilation error?
Upvotes: 0
Views: 52
Reputation: 131581
Assuming you call this Builders.Update.Push method, you'll have to explicitly cast or convert the list to a sequence,either directly or by calling Seq.ofList which does just that :
[<CompiledName("OfList")>]
let ofList (source : 'T list) =
(source :> seq<'T>)
The common and far more readable way is to use Seq.ofList
so you should use :
let update = Builders.Update.Push<string>((fun x -> x.users |> Seq.ofList), usr)
Explanation
The reason for this is that Push
expects a function that returns an IEnumerable<T>
. Its syntax is :
static member Push :
memberExpression : Expression<Func<'TDocument, IEnumerable<'TValue>>> *
value : 'TValue -> UpdateBuilder<'TDocument>
A list does implement the IEnumerable<T>
interface :
type List<'T> =
| ([]) : 'T list
| (::) : Head: 'T * Tail: 'T list -> 'T list
interface System.Collections.Generic.IEnumerable<'T>
...
The F# compiler can't implicitly cast to the interface in the question's case though.
A seq
on the other hand is a type alias for IEnumerable<T>
:
type seq<'T> = IEnumerable<'T>
Seq.ofList
will cast the users
list to the IEnumerable<string>
that Push
expects
Upvotes: 1
Reputation: 1593
The compiler error says that string list
is not compatible with IEnumerable<string>
. However string seq
is so you should define your type as follows
type SegmentRM =
{ id : SegmentId
users: string seq }
Upvotes: 1