F#-健全性检查和选项

F#-健全性检查和选项,f#,options,F#,Options,我对F#还很陌生,所以在多年的C#/javaoop之后,我很难改变我的思维方式 我有一个事件处理程序MyForm.SelectFile(filePath:String),它打开一个对话框,让您选择要读取的文件。选择文件后,将调用Parser.LoadFile(filePath:String): static member LoadFile(filePath:String) = if not <| ZipFile.IsZipFile(filePath) then fa

我对F#还很陌生,所以在多年的C#/javaoop之后,我很难改变我的思维方式

我有一个事件处理程序
MyForm.SelectFile(filePath:String)
,它打开一个对话框,让您选择要读取的文件。选择文件后,将调用Parser.LoadFile(filePath:String):

static member LoadFile(filePath:String) =
    if not <| ZipFile.IsZipFile(filePath) then
        failwith "invalid file specified."
    use zipFile = new ZipFile(filePath)
    if zipFile.Count <> 2 || zipFile |> Seq.exists(fun x -> x.FileName <> "alpha" && x.FileName <> "beta")  then
        failwith "invalid file specified."
    zipFile |> fun x -> Parser.Parse(x.OpenReader())

首先,如果函数的最后一行是这样写的,那么它可能会更优雅一些:

zipFile.OpenReader() |> Parser.Parse
其次,就您使用
选项的想法而言,您已经走上了正确的轨道。在这种情况下非常简单:

static member LoadFile(filePath:String) =
    if not <| ZipFile.IsZipFile(filePath) then None else
    use zipFile = new ZipFile(filePath)
    if zipFile.Count <> 2 || zipFile |> Seq.exists(fun x -> x.FileName <> "alpha" && x.FileName <> "beta") then None else
    Some (zipFile.OpenReader() |> Parser.Parse)
现在,您提到您不喜欢长的
if
语句。让我们把它变成一个函数!我通常更喜欢具有“肯定”名称的函数,即
isValidInput
函数通常比
isInvalidInput
函数更有用。让我们做一个函数来检查zipfile是否实际有效:

let isValid (z:ZipFile) =
    z.Count = 2 && z |> Seq.forAll(fun x -> x.FileName = "alpha" || x.FileName = "beta")
现在,您的
LoadFile
功能可以变成:

static member LoadFile(filePath:String) =
    if not <| ZipFile.IsZipFile(filePath) then None else
    use zipFile = new ZipFile(filePath)
    if not <| isValid zipFile then None else
    zipFile.OpenReader() |> Parser.Parse |> Some
静态成员加载文件(文件路径:字符串)=
如果不是一些
这看起来很容易阅读,所以我们现在可以停止重构了。

这段代码看起来很奇怪。对这样一段简单的代码使用序列表达式是过分的

Some(seq { for zipEntry in zipFile do yield Parser.Parse(zipEntry.OpenReader()) } |> Seq.toArray)
你可以这样写得更好

zipFile |> Seq.map (fun ze -> ze.OpenReader () |> Parser.parse) |> Some
或者,如果你坚持在一个数组中执行它(为什么?)


您将得到类型签名
选项
。我不确定这是否是一个好主意,但如果不看代码的其余部分,就无法判断。

非常感谢您的帮助!除了需要解析zip中的每个文件并返回每个解析结果这一事实之外,一切都像一个符咒。我更新了我的答案,显示了实际代码。。。我想知道我做的是正确的,如果数组是我存储分析结果的最佳选择(它们需要经过一些处理,包括一些改变解析值的写回zip文件)。请考虑在代码复审中提交更完整的代码(编译)。您将获得关于如何在功能上构造代码的更详细答案。
Some(seq { for zipEntry in zipFile do yield Parser.Parse(zipEntry.OpenReader()) } |> Seq.toArray)
zipFile |> Seq.map (fun ze -> ze.OpenReader () |> Parser.parse) |> Some
zipFile |> Seq.map (fun ze -> ze.OpenReader () |> Parser.parse) |> Seq.toArray |> Some