如何将可选值应用于F#中的可选函数

时间:2017-03-03 03:54:37

标签: f#

在F#中,我有一个带签名type func= (string-> string list) option的可选功能。如何将签名type param= string option的可选字符串参数传递给func方法。

如果不使用嵌套的if else,有没有办法做到这一点。

1 个答案:

答案 0 :(得分:2)

我没有立即注意到函数本身包裹在option中。我会将以下误读问题的原始答案保留以供参考,但这里是实际问题的答案:

首先,当没有功能和/或没有字符串时,你仍然需要决定你想做什么(见下文)。一旦你做出决定,你就可以匹配元组:

let resultingList =
   match func, param with
   | Some f, Some p -> f p  // When both are present, apply
   | _ -> []                // Otherwise, return empty list

在这里,当任何一个或两个都缺席时,我会崩溃。但是,如果您需要针对这些情况采用不同的行为,则可以明确地枚举其中的全部或部分内容:

let resultingList =
   match func, param with
   | Some f, Some p -> f p 
   | Some f, None -> f ""
   | None, Some _ -> [ "there was no function" ]
   | None, None -> [ "there was no string AND no function" ]

误读问题的原始答案

类型string option表示" 此处可能有字符串,或者"。所以问自己的第一个问题是:当没有字符串时你想做什么?我无法帮助你决定这一点,因为这取决于你的大问题(即你最终要做的事情)。

功能string -> string list需要string并返回string list。因此,如果您有一个字符串,那么您将获得string list。但是如果你没有string怎么办?如果你没有得到什么" (即"没有列表",就像"没有字符串"开头)?或者你应该得到一个空列表?或者你应该得到一些预定值吗?

为了逐步学习,让我们假设,当没有字符串时,你想要找回一个空列表。为此,请使用模式匹配:

let resultingList =
   match param with
   | Some s -> func s
   | None -> []

这个程序字面上说:" 如果有字符串,则调用该字符串s并对其应用func;如果没有字符串,则返回一个空列表"。

同样的事情适用于获取其他预定义列表而不是空列表:

let resultingList =
   match param with
   | Some s -> func s
   | None -> [ "oopsie, there was no string!" ]

但如果你想要另一个选项 - "没有列表"一, - 那么您的结果值必须为string list option,就像您的输入为string option一样。 option类型有两个构造函数:Some用于创建存在的值,None用于表示"没有 spoon 值"

let maybeResultingList =
   match param with
   | Some s -> Some (func s)
   | None -> None

字面上说:" 如果有字符串,则调用它s,将func应用于它,并将结果包装为Some,这意味着"这里有一个列表&#34 ;;如果没有字符串,只需返回None,这意味着"没有列表"。

幸运的是,这个" 将函数应用于该值,除非它不存在"操作是如此常见,以至于它有一个标准的库函数。它被称为Option.map

let maybeResultingList = Option.map func param

另一个有趣的方法是:首先我们将func传递给Option.map并返回另一个函数,然后我们将该函数应用于param

let maybeFunc = Option.map func
let maybeResultingList = maybeFunc param

这种看待它的方式在实践中非常有用。令人尊敬的Scott Wlaschin在这个概念上有一个非常棒的系列。请在此处查看:https://fsharpforfunandprofit.com/posts/elevated-world/