2
votes

The following function files returns seq<seq<R>>. How to make it return seq<R> instead?

type R = { .... }
let files = seqOfStrs |> Seq.choose(fun s ->
    match s with
    | Helper.ParseRegex "(\w+) xxxxx" month ->
        let currentMonth =  .....
        if currentMonth = month.[0] then
            doc.LoadHtml(s)
            Some (
                doc.DucumentNode.SelectNodes("....")
                |> Seq.map(fun tr ->
                    { ..... } ) //R. Some code return record type R. Omitted
            )
        else
            printfn "Expect %s found %s." currentMonth month.[0]
            None
    | _ ->
        printfn "No '(Month) Payment Data On Line' prompt."
        None
3

3 Answers

2
votes

Your snippet is incomplete and so we can't give you a fully working answer. But:

  • Your code is using Seq.choose and you are returning either None or Some with collection of values. Then you get a sequence of sequences...

  • You can use Seq.collect which flattens the sequences and replace None with an empty sequence and Some with just the sequence.

Something along those lines (untested):

let files = seqOfStrs |> Seq.collect (fun s ->
    match s with
    | Helper.ParseRegex "(\w+) xxxxx" month ->
        let currentMonth =  .....
        if currentMonth = month.[0] then
            doc.LoadHtml(s)
            doc.DucumentNode.SelectNodes("....")
            |> Seq.map(fun tr ->
                { ..... } ) //R. Some code return record type R. Omitted
        else
            printfn "Expect %s found %s." currentMonth month.[0]
            Seq.empty
    | _ ->
        printfn "No '(Month) Payment Data On Line' prompt."
        Seq.empty )

The other options like adding Seq.concat or Seq.collect id to the end of the pipeline would obviously work too.

2
votes

You want to pipe the whole thing to Seq.collect.

for example,

files |> Seq.collect id
1
votes

You can use an F# sequence expresssion to flatten the seq of seqs into a seq. Say you have:

> let xss = seq { for i in 1 .. 2 -> seq { for j in 1 .. 2 -> i * j } };;

val xss : seq<seq<int>>

> xss;;                                                                  
val it : seq<seq<int>> = seq [seq [1; 2]; seq [2; 4]]

Then you can do:

> seq { for x in xss do yield! x };;
val it : seq<int> = seq [1; 2; 2; 4]

Behind the scenes, the sequence expression is doing the same thing as Seq.collect, just in a more syntax-sugary way.