Abraham
Abraham

Reputation: 155

How to add element to a nested array

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

Answers (2)

Panagiotis Kanavos
Panagiotis Kanavos

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

Bohdan Stupak
Bohdan Stupak

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

Related Questions