如何通过F#的Seq.cast避免"价值限制"错误?

gat*_*ado 2 .net ienumerable f# restriction

我看到Seq有一个从IEnumerable到Seq的强制转换功能,但是如何让它工作呢?

open System.Text.RegularExpressions;;
let v = Regex.Match("abcd", "(ab)");;
Seq.cast (v.Captures);;
Run Code Online (Sandbox Code Playgroud)

这会产生,

错误FS0030:值限制.值'it'被推断为具有泛型类型val:seq <'_ a>
将'it'定义为一个简单的数据项,使其成为具有显式参数的函数,或者,如果您不打算使它是通用的,添加类型注释.

Bri*_*ian 8

明确类型:

Seq.cast<Match> (v.Captures)
Run Code Online (Sandbox Code Playgroud)

否则cast需要上下文来推断正确的返回类型,并且就像那里一样,就没有这样的上下文来使用类型推断.

(此行将非泛型IEnumerable转换为通用IEnumerable<Match>aka seq<Match>.)


Tom*_*cek 6

实际上有两种方法可以指定您想要获得的类型.Brian通过显式指定函数的type参数发布了如何执行此操作:

let res = Seq.cast<Match> v.Captures
Run Code Online (Sandbox Code Playgroud)

另一个选项是使用类型注释,它可以放在任何F#表达式周围并指定表达式的类型 - 这样就可以提示编译器类型推理(通过说某些表达式具有特定类型).如果以一种巧妙的方式提供信息,编译器将能够确定Seq.cast应该是什么类型参数.几个例子:

// By specifying type of the value
let (res:seq<Match>) = Seq.cast v.Captures 

// By specifying return type of a function
let getCaptures () : seq<Match> = 
  // ...
  Seq.cast v.Captures

// By specifying element type when iterating over the result
for (m:Match) in Seq.cast v.Captures do
  // ...
Run Code Online (Sandbox Code Playgroud)

从所有选项中,我认为Brians(显式)和我的第二个(函数的返回类型)是那些最惯用的选项,但是,您可以选择任何您认为最具可读性的选项.