开发者

Seq.Map string->string

all!

What is wrong with this code? I cannot understand what I am doing wrong with Seq.Map. Here is the error message: The type 'unit' is not compatible with the type 'seq<'a>'

let getPathToLibFile value =
    let regex = new Regex("\"(?<data>[^<]*)\"")
    let matches = regex.Match(value)
    matches.Value

let importAllLibs (lines:string[]) =
    lines
    |> Seq.filter isImportLine
    |> Seq.iter (printfn "Libs found: %s")
    |> Seq.开发者_StackOverflow社区map getPathToLibFile // error in this line
    |> Seq.iter (printfn "Path to libs: %s")

Is there any understandable examples on Seq.Map?

PS Example from wiki (it works):

(* Fibonacci Number formula *)
let rec fib n =
    match n with
    | 0 | 1 -> n
    | _ -> fib (n - 1) + fib (n - 2)

(* Print even fibs *)
[1 .. 10]
|> List.map     fib
|> List.filter  (fun n -> (n % 2) = 0)
|> printlist


I suspect the problem is actually your previous call.

Seq.iter doesn't return anything (or rather, returns unit) so you can't use it in the middle of a pipeline. Try this:

let importAllLibs (lines:string[]) =
    lines
    |> Seq.filter isImportLine
    |> Seq.map getPathToLibFile
    |> Seq.iter (printfn "Path to libs: %s")

... and then if you really need to print out the "libs found" line, you can add another mapping which performs the printing and just returns the input:

let reportLib value =
    printfn "Libs found: %s" value
    value

let importAllLibs (lines:string[]) =
    lines
    |> Seq.filter isImportLine
    |> Seq.map reportLib
    |> Seq.map getPathToLibFile
    |> Seq.iter (printfn "Path to libs: %s")

This may well be invalid F#, but I think the aim is right :)


WebSharper includes an operator you can define yourself like this:

let (|!>) a f = f a; a

Allowing you to call a function of type 'a -> unit on the input value returning the same value.

Fixing your code would require but a slight modification:

lines
|> Seq.filter isImportLine
|!> Seq.iter (printfn "Libs found: %s")
|> Seq.map getPathToLibFile // error in this line
|> Seq.iter (printfn "Path to libs: %s")

On the other hand you would end up iterating the collection twice which might not be what you want.

A better approach would be to define a function Do (lowercase do being a reserved keyword in F#) which introduces a side effect on iterating the sequence. Rx.NET (Ix) provides such a function in EnumerableEx:

let Do f xs = Seq.map (fun v -> f v; v) xs

and then you can introduce the side effect like so:

lines
|> Seq.filter isImportLine
|> Do (printfn "Libs found: %s")
|> Seq.map getPathToLibFile // error in this line
|> Seq.iter (printfn "Path to libs: %s")

The side effect will be introduced only upon iterating the collection on the last line.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜