从F#(Observable.StartWith)中使用“参数"调用泛型函数 [英] Calling generic function with 'params' from F# (Observable.StartWith)

查看:72
本文介绍了从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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆