Edit:请注意,正如 Daniel 和 latkin 在下面的回答和评论中指出的那样,这个问题涉及 F# 中的一个错误,该错误似乎已于 2014 年初修复。
我正在尝试为 Observable.StartWith 编写一个咖喱包装器。我正在使用预发布的 Reactive Extensions 2.0 和 VS11 beta。我想要的结果是startWith : 'a -> IObservable<'a> -> IObservable<'a>
。明显的实现是这样的:
let startWith
(value : 'a)
(observable : IObservable<'a>)
: IObservable<'a> =
Observable.StartWith(observable, [| value |])
Observable.StartWith 的预期重载是StartWith<'TSource>(source : IObservable<'TSource>, params values: 'TSource[]) : IObservable<'TSource>
.
编译器抛出一个令人困惑的错误:This method expects a CLI 'params' parameter in this position. 'params' is a way of passing a variable number of arguments to a method in languages such as C#. Consider passing an array for this argument
.
I am传递一个数组。我也尝试过not传递一个数组,通过省略[| |]
,这会导致唯一重载解析失败。 (大概是因为有可能'a
可能System.Reactive.Concurrency.IScheduler
,匹配其他重载。)我还尝试使用 F# 2.0/VS2010,它给出了相同的结果。我找不到任何有关此类情况或编译器错误消息的在线讨论。
我想不出任何其他方法来实现这一点。请注意,在可以确定类型参数的情况下,这不是问题。例如,let prependZero : int -> IObservable<int> -> IObservable<int> = fun n o -> o.StartWith(n)
工作正常。但通用版本会很好。
它看起来像是围绕通用参数数组的类型推断的问题。即使是一个不涉及重载解析的简单情况,也会存在问题:
type A() =
static member M<'T>([<ParamArray>] args: 'T[]) = args
//None of these work
let m1 arg = A.M([|arg|])
let m2 args = A.M(args)
let m3<'T> (args:'T[]) = A.M<'T>(args)
非通用版本的工作原理:
type B() =
static member M([<ParamArray>] args: obj[]) = args
//Both of these are okay
let m1 arg = B.M([|arg|])
let m2 args = B.M(args)
EDIT
我给 fsbugs 发了电子邮件,他们回复说这是一个错误。以下是他们建议的一些解决方法。
let m1 arg = A.M<obj>([|arg|])
let m2 args = A.M<obj>(args)
let m3 (args:obj[]) = A.M<obj>(args)
let m4 (arg:obj) = A.M<obj>(arg)
let m5 arg1 arg2 = A.M<obj>(arg1,arg2)
let m6 (arg1:'T) = A.M<'T>(arg1)
let m7 (arg1:'T) (arg2:'T) = A.M<'T>(arg1,arg2)
let m8 (arg1:'T) (arg2:'T) = A.M(arg1,arg2)
let m9 (arg1:'T) = A.M(arg1)
let m10<'T> arg1 arg2 = A.M<'T>(arg1,arg2)
let m11<'T> (arg1:'T) (arg2:'T) = A.M<'T>(arg1,arg2)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)