选项类型如何在F#中工作?

时间:2009-03-08 19:14:30

标签: c# .net f#

所以我一直在阅读Apress的专家F#书,主要是在构建一个玩具式的F#库时用它作为参考,但有一点我没能理解,那就是“选项”类型。 / p>

它是如何工作的以及它的真实用途是什么?

6 个答案:

答案 0 :(得分:20)

选项类型至少是类似Nullable<T>和C#中的引用类型。类型Option<T>的值为None,这意味着没有封装值,或Some具有特定值T。这就像C#中的Nullable<int> 空值,具有关联的int的方式 - 和{{{ 1}} C#中的值是 空引用,引用String对象。

使用选项值时,通常指定两个路径 - 一个用于 关联值的情况,另一个不是的路径。换句话说,这段代码:

String

类似于:

let stringLength (str:Option<string>) =
  match str with
  | Some(v) -> v.Length
  | None -> -1

我相信一般的想法是强迫你(好吧,差不多)处理“没有关联的值/对象”的情况会让你的代码更健壮。

答案 1 :(得分:5)

实际使用的最佳示例之一是.Net中的TryParse模式。 <见上半部分

http://lorgonblog.spaces.live.com/blog/cns!701679AD17B6D310!181.entry

进行讨论。

答案 2 :(得分:4)

当函数或方法应该“可能”或“可选地”返回值时使用它。在C#中,你可能会返回null,或者为值类型返回Null Object或可能的Nullable。

返回null(最常见的情况)的缺点是它不是类型安全的:null是所有类型的实例,因此您稍后会进入各种多毛的空引用情况。

Option类型是一个所谓的带有两个构造函数的被取消的联合类型:None和Some a。没有明确表明您没有值。基本上它是Null对象模式的概括。

答案 3 :(得分:3)

当值是可选的时,您可以使用它。一种用途是具有一种“空引用”,例如,

 val x : int option ref = None 

然后你可以稍后将x更新为some v。你将它与匹配语句一起使用,例如

 match !x with (* dereference x *)
    None -> (* No value, do something *)
 |  Some v -> (* Value v, do something else *)

答案 4 :(得分:1)

要添加其他答案,Option类型并不特别 - 它只是另一个受歧视的联合。您可以在一行中自己定义它:

type 'a Option = None | Some of 'a

正如其他人所指出的那样,该实用程序是模式匹配可以让你安全地解构它,而不是检查null或使用一些hack-workaround来指示值是否真的不是值。

答案 5 :(得分:0)

使用选项类型的功能模式:

当您需要更改递归数据结构的某些部分时,例如树或列表, 您将希望尽可能多地重用现有数据结构。选项类型 可以帮助你。 这两个函数都用7替换所有出现的数字5, 但第一个复制整个树。第二个没有。

type Tree = Leaf of int
      | Node of Tree * Tree

let rec replace_no_sharing tree =
    match tree with
    | Leaf 5      -> Leaf 7
    | Leaf x      -> Leaf x
    | Node (a, b) -> Node (replace_no_sharing a, replace_no_sharing b)

let replace_with_sharing tree =
    let rec replace_option tree =
        match tree with
        | Leaf 5      -> Leaf 7 |> Some
        | Leaf x      -> None
        | Node (a, b) -> match replace_option a, replace_option b with
                         | None, None     -> None
                         | Some a, Some b -> Node (a, b) |> Some
                         | Some a, None   -> Node (a, b) |> Some
                         | None, Some b   -> Node (a, b) |> Some
    match replace_option tree with
    | None      -> tree
    | Some tree -> tree

在所有情况下可能没有必要,但这是一个很好的技巧。