当我尝试将商品添加到这样的列表中时:
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)
我有一个编译错误
No overloads match for method 'Push'. The available overloads are shown below.
并且也尝试对users: string[]
进行同样的错误处理。
有人知道如何避免这种编译错误吗?
答案 0 :(得分:1)
编译器错误表明string list
与IEnumerable<string>
不兼容。但是string seq
是这样,因此您应该按照以下方式定义类型
type SegmentRM =
{ id : SegmentId
users: string seq }
答案 1 :(得分:1)
假设您调用此Builders.Update.Push方法,则必须直接或通过调用Seq.ofList来显式将列表强制转换或转换为序列:
[<CompiledName("OfList")>]
let ofList (source : 'T list) =
(source :> seq<'T>)
常见且可读性更高的方法是使用Seq.ofList
,因此您应该使用:
let update = Builders.Update.Push<string>((fun x -> x.users |> Seq.ofList), usr)
说明
这样做的原因是Push
需要一个返回IEnumerable<T>
的函数。它的语法是:
static member Push :
memberExpression : Expression<Func<'TDocument, IEnumerable<'TValue>>> *
value : 'TValue -> UpdateBuilder<'TDocument>
列表does implement the IEnumerable<T>
interface:
type List<'T> =
| ([]) : 'T list
| (::) : Head: 'T * Tail: 'T list -> 'T list
interface System.Collections.Generic.IEnumerable<'T>
...
在问题的情况下,F#编译器无法隐式转换为接口。
另一方面,seq
是a type alias for IEnumerable<T>
:
type seq<'T> = IEnumerable<'T>
Seq.ofList
会将users
列表投射到IEnumerable<string>
期望的Push