以下代码的两个printfns 都有类型错误.
我该如何解决?Seq.map即使其中一个项目失败,我也希望循环继续.
// files should be a Seq of record
let files = seqOfStrs |> Seq.map(fun s ->
match s with
| Helper.ParseRegex "(\w+) xxxxx" month ->
let currentMonth = .....
if currentMonth = month.[0] then
doc.Load(shelf)
// parse doc and return record type. Omitted
else
printfn "Expect %s found %s." currentMonth month.[0] //Error
| _ ->
printfn "No '(Month) Payment Data On Line' prompt." //Error
Run Code Online (Sandbox Code Playgroud)
问题是你的逻辑的不同分支产生了不同的东西.在"省略"部分中,您显然返回xxxx类型的值(例如string),但在其他分支中使用printfn调用,您将返回没有值,在F#中表示为,unit而在其他语言中通常称为void.
如果您不希望循环继续,最简单的答案就是在这些情况下抛出异常,例如:
failwithf "Expect %s found %s." currentMonth month.[0]
Run Code Online (Sandbox Code Playgroud)
静态返回类型failwithf可以是任何类型,包括string,因为它实际上从未返回,因此实际上不必生成该类型的值.
鉴于您确实希望代码继续,您可以返回一个空字符串或某种失败值,例如:
printfn "Expect %s found %s." currentMonth month.[0] //Error
"failed"
Run Code Online (Sandbox Code Playgroud)
现在所有分支都具有相同的类型,因此您的代码将编译,但您必须小心,调用者不会意外地将此值解释为某些有效结果,这就是为什么抛出异常通常更清晰.
更简洁的方法是使用option值来表示成功或失败,即Some "..."在正确的情况下和None错误情况下返回.当失败是调用代码想要处理的常见事件而不是仅仅向用户报告问题并中止时,这种方法更好:
// files should be a Seq of record
let files = seqOfStrs |> Seq.map(fun s ->
match s with
| Helper.ParseRegex "(\w+) xxxxx" month ->
let currentMonth = .....
if currentMonth = month.[0] then
doc.Load(shelf)
// parse doc and produce record type.
Some record
else
printfn "Expect %s found %s." currentMonth month.[0] //Error
None
| _ ->
printfn "No '(Month) Payment Data On Line' prompt." //Error
None
Run Code Online (Sandbox Code Playgroud)
现在,您需要确定要files包含的内容 - 您是否希望显式None值显示某些内容失败,或者您只是希望序列包含正确的值并完全省略失败?
如果您想要显式值,那么您可以将option值保留在原位并获得seq<string option>结果.请注意,这种类型只是语法糖seq<option<string>>,反映了F#的O'Caml传统.
如果你只是想省略它们,那么用你的Seq.map调用替换你的调用Seq.choose,这将删除所有的None值并剥离Some包装器,留下你seq<string>正在尝试生成的当前代码.