F#验证输入参数

时间:2017-03-02 20:11:52

标签: validation f# match

使用玩具示例来验证输入参数,并在无效时发出错误消息。到目前为止,我有:

let usage = 
    printfn "Usage:  %s " (Process.GetCurrentProcess().ProcessName)
    exit -1


let test what date id flag = 
    let date =
        match DateTime.TryParse date with
        | (true, d) -> Some d
        | _ -> usage

    let id =
        match Int32.TryParse id with
        | (true, int) -> Some int
        | _ -> usage // error here

    0

[<EntryPoint>]
let main argv = 
    printfn "%A" argv
    match argv with
    | [| what;  date; id; flag |] -> test
    | _ -> usage

但这会产生错误:

  

错误1类型不匹配。期待一个       int选项但是给出了一个       DateTime选项类型&#39; int&#39;与类型&#39; DateTime&#39;

不匹配

从哪里获取DateTime类型?第一场比赛?但那么,为什么?在没有出现类型错误的情况下编写catch-all错误处理程序的正确方法是什么?

1 个答案:

答案 0 :(得分:2)

&#34;问题1:

let usage =

这不是一个功能。你最想要的是

let usage () =

你必须像这样调用这个函数。

usage ()

问题2:

错误的原因是基于类型推断,用法返回DateTime选项。

这两行中的第一行是编译器确定匹配表达式将返回DateTime选项的位置。第二行是编译器推断&#34;用法&#34;必须也是DateTime选项,因为匹配表达式返回DateTime选项。

| (true, d) -> Some d
| _ -> usage

如何使用成为DateTime选项?因为您使用&#34;退出-1&#34;,并且退出的签名是int-&gt;&#39; T,因此&#34; usage&#34;实际上,编译器会强制它根据类型推断返回特定类型。它被强制输入&#34; DateTime选项&#34;,这不是你想要的。为了防止这种情况,您可以声明预期的结果使用类型,或者可以显式返回您想要的值。我会在这里做两件事来说明这一切。

let usage () : unit = 
    printfn "Usage:  %s " (Process.GetCurrentProcess().ProcessName)
    exit -1
    ()

现在&#34;用法&#34;已被锁定为unit-&gt;单位的签名,这简化了我们的进一步工作。

问题3:

F#是一种功能语言,而不是命令式语言。 &#34;用法&#34;功能相当成问题。我建议你用&#34; failwith&#34;来替换它。相反,并用&#34;尝试&#34;捕获错误在&#34; main&#34;,如下所示。另一种选择是&#34;使用&#34;返回&#; T,与&#34;相同&#34;是的,如果你真的希望能够在任何地方终止程序。不推荐,因为这种使用会让你在这个阶段难以理解。然后,您的程序将退出,但不会显示可能出错的迹象。更好地处理如下所示的预期和意外异常,并从主函数中彻底终止。

let test what date id flag = 
    let date =
        match DateTime.TryParse date with
        | (true, d) -> Some d
        | _ -> failwith "Error 1 here."
    let id =
        match Int32.TryParse id with
        | (true, int) -> Some int
        | _ -> failwith "Error 2 here."
    ()

let main argv =
    try
        match argv with
        | [| what;  date; id; flag |] -> test what date id flag
        | _ -> failwith "Error 3 here."
        0
    with ex ->
        printfn "Error: %s" ex.Message
        printfn "Usage: %s" (Process.GetCurrentProcess().ProcessName)
        -1