[英]How does the option type work in F#
所以我一直在阅读 Apress 的 Expert F# 书,主要是在构建玩具式 F# 库时将其用作参考,但有一件事我没能掌握,那就是“选项”类型。
它是如何工作的,它在现实世界中的用途是什么?
选项类型至少类似于Nullable<T>
和 C# 中的引用类型。 Option<T>
类型的值要么是None
,这意味着没有封装值,要么是Some
具有特定值T
。 This is just like the way a Nullable<int>
in C# is either the null value, or has an associated int
- and the way a String
value in C# is either a null reference, or refers to a String object.
当您使用选项值时,您通常会指定两条路径 - 一条用于有关联值的情况,另一条用于没有关联值的情况。 换句话说,这段代码:
let stringLength (str:Option<string>) =
match str with
| Some(v) -> v.Length
| None -> -1
类似于:
int StringLength(string str)
{
if (str != null)
{
return str.Length;
}
else
{
return -1;
}
}
我相信一般的想法是强迫你(好吧,几乎)处理“没有关联的值/对象”的情况会使你的代码更加健壮。
实际使用的最佳示例之一是.Net 中的TryParse模式。 看前半部分
http://lorgonblog.spaces.live.com/blog/cns.701679AD17B6D310!181.entry
进行讨论。
当 function 或方法应该“可能”或“可选地”返回值时使用它。 在 C# 中,您可能会返回 null,或者返回Null Z497031794414A5类型 5435F90151AC3
返回 null(最常见的情况)的缺点是它不是类型安全的:null 是所有类型的实例,因此您稍后会遇到各种毛茸茸的 null 参考情况。
Option 类型是所谓的有区别的联合类型,有两个构造函数:None 和 Some a。 None 明确表示您没有值。 基本上它是广义的 Null Object 模式。
当值是可选的时使用它。 一种用途是拥有一种“空引用”,例如
val x : int option ref = None
然后您可以稍后将 x 更新为 Some v。您可以将它与 match 语句一起使用,例如
match !x with (* dereference x *)
None -> (* No value, do something *)
| Some v -> (* Value v, do something else *)
添加到其他答案中, Option 类型没什么特别的——它只是另一个有区别的联合。 您可以在一行中自己定义它:
type 'a Option = None | Some of 'a
正如其他人指出的那样,该实用程序是模式匹配将让您安全地解构它,而不是检查 null 或使用一些黑客解决方法来指示一个值是否真的不是一个值。
使用选项类型的功能模式:
当您需要更改递归数据结构的一部分时,例如树或列表,您将希望尽可能多地重用现有数据结构。 选项类型可以帮助您解决此问题。 这两个函数都将所有出现的数字 5 替换为 7,但第一个函数复制了整个树。 第二个没有。
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
可能并非在所有情况下都需要它,但这是一种很好的技术。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.