views:

84

answers:

2

I see that Seq has a cast function from IEnumerable to Seq, but how do I get it to work?

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

This produces,

error FS0030: Value restriction. The value 'it' has been inferred to have generic type val it : seq<'_a>
Either define 'it' as a simple data term, make it a function with explicit arguments or, if you do not intend for it to be generic, add a type annotation.

+5  A: 

Be explicit about the type:

Seq.cast<Match> (v.Captures)

Otherwise cast needs context to infer the right return type, and on a line by itself like there, there is no such context for type inference to use.

(This line converts the non-generic IEnumerable into a generic IEnumerable<Match> a.k.a. seq<Match>.)

Brian
+5  A: 

There are actually two ways to specify the type you want to get. Brian posted how to do this by explicitly specifying the type parameter to a function:

let res = Seq.cast<Match> v.Captures

The other option is to use type annotations which can be placed around any F# expression and specify the type of the expression - this way you can hint the compiler type inferrence (by saying that some expression has a particular type). If you provide the information in some clever way, the compiler will be able to figure out what the type parameter to Seq.cast should be. A few examples:

// 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
  // ...

From all of the options, I think that the Brians (explicit) and my second (return type of a function) are those that are the most idiomatic, however, you can choose any option you find the most readable.

Tomas Petricek