预计此表达式的类型为xxxx,但此处具有类型单位

时间:2015-04-26 10:07:38

标签: f#

以下代码对printfn s。

都有类型错误

我该如何解决?即使其中一个项目失败,我也希望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

1 个答案:

答案 0 :(得分:7)

问题在于你逻辑的不同分支正在产生不同的东西。在"省略"您显然返回xxxx类型的值(例如string),但在printfn次调用的其他分支中,您返回时没有值,这在F#中是表示为unit,在其他语言中通常称为void

如果您不希望循环继续,最简单的答案就是在这些情况下抛出异常,例如:

failwithf "Expect %s found %s." currentMonth month.[0]

failwithf的静态返回类型可以是任何类型,包括string,因为它实际上从未返回,因此实际上不必生成该类型的值。

鉴于您确实希望代码继续,您可以返回一个空字符串或某种失败值,例如:

printfn "Expect %s found %s." currentMonth month.[0] //Error
"failed"

现在所有分支都具有相同的类型,因此您的代码将编译,但您必须小心,调用者不会意外地将此值解释为某些有效结果,这就是为什么抛出异常通常更清晰。

更简洁的方法是使用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

您现在需要确定您希望files包含的内容 - 您是否希望显式None值显示某些内容失败,或者您只是希望序列包含正确的内容价值并完全忽略失败?

如果您想要显式值,那么您可以保留option值,并且您将获得seq<string option>结果。请注意,此类型只是seq<option<string>>的语法糖,反映了F#的O&#39; Caml遗产。

如果您只想省略它们,请将Seq.map来电替换为Seq.choose,这将删除所有None值并删除Some包装,离开您当前代码正在尝试生成seq<string>