从F#(Observable.StartWith)中使用“参数"调用泛型函数 [英] Calling generic function with 'params' from F# (Observable.StartWith)
问题描述
编辑:请注意,正如Daniel和latkin在下面的答案和评论中指出的那样,该问题涉及F#中的一个错误,该错误似乎已在2014年初修复.
Edit: Note that, as Daniel and latkin noted in an answer and a comment below, this question involved a bug in F# that seems to have been fixed in early 2014.
我正在尝试为Observable.StartWith写一个咖喱包装.我正在使用预发布的Reactive Extensions 2.0和VS11 beta.我想要的结果将是startWith : 'a -> IObservable<'a> -> IObservable<'a>
.显而易见的实现将是这样的:
I'm trying to write a curried wrapper for Observable.StartWith. I'm using the prerelease Reactive Extensions 2.0, and the VS11 beta. My desired result would be startWith : 'a -> IObservable<'a> -> IObservable<'a>
. The obvious implementation would be something like:
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>
.
The intended overload of Observable.StartWith is 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
.
The compiler throws a confusing error: 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
.
我 am 传递了一个数组.我还尝试通过省略[| |]
来 not 传递数组,这会导致唯一的过载解析失败. (大概是由于'a
可能是System.Reactive.Concurrency.IScheduler
,与其他重载匹配的可能性.)我还尝试使用F#2.0/VS2010,它给出了相同的结果.我找不到这种情况或编译器错误消息的在线讨论.
I am passing an array. I also tried not passing an array, by omitting the [| |]
, which leads to a unique-overload-resolution failure. (Presumably due to the possibility that 'a
could be System.Reactive.Concurrency.IScheduler
, matching the other overload.) I also tried using F# 2.0/VS2010, which gives the same result. I couldn't locate any online discussion of this sort of situation or of the compiler error message.
我想不出任何其他方式来实现这一目标.请注意,在可以确定type参数的情况下,这不是问题.例如,let prependZero : int -> IObservable<int> -> IObservable<int> = fun n o -> o.StartWith(n)
可以正常工作.但是通用版本会很好.
I can't think of any other way to implement this. Note that in cases where the type parameter can be determined, it's not a problem. For instance, let prependZero : int -> IObservable<int> -> IObservable<int> = fun n o -> o.StartWith(n)
works fine. But a generic version would be nice.
推荐答案
看起来像围绕通用参数数组进行类型推断的问题.即使是不涉及重载解析的简单情况,也存在问题:
It looks like a problem with type inference surrounding generic param arrays. Even a simple case, not involving overload resolution, has problems:
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)
编辑
我通过电子邮件发送了fsbugs,他们回答说这是一个错误.这是他们建议的一些解决方法.
EDIT
I emailed fsbugs and they responded that this is a bug. Here are some workarounds they suggested.
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)
这篇关于从F#(Observable.StartWith)中使用“参数"调用泛型函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!