选项类型崩溃了吗?

时间:2016-12-13 14:12:48

标签: f# optional

这是F#中的选项类型:

type Option<'a> =
   | Some of 'a
   | None

假设我有一个Option的{​​{1}}:

Option

是否会折叠为只有一个type Option2<'a> = | O of Option<'a> | None

3 个答案:

答案 0 :(得分:5)

不,F#有名义类型系统结构等效类型不兼容。因此,即使您OptionOption2完全相同(名称除外),这些类型也会有所不同。您的情况不同,类似于询问整数列表和整数列表是否相同。

let hasOptionType (_ : Option<_>) = ()
let hasOption2Type (_ : Option2<_>) = ()

let o = Option.None
let o2 = Option2.None

hasOptionType o
//hasOption2Type o // does not compile
//hasOptionType o2 // does not compile
hasOption2Type o2

您可以使用类型别名,但两种方式都可以:

type IntOption = Option<int>

let isOptionOfInt (_ : Option<int>) = ()
let isIntOption (_ : IntOption) = ()

let i = IntOption.None
let i2 = Option<int>.None

isOptionOfInt i
isOptionOfInt i2
isIntOption i
isIntOption i2

答案 1 :(得分:4)

您的问题有点混乱,因为您谈论Option的{​​{1}},但随后会显示一种类型,即您自己的Option类型,其中包含Option2

我将假设你的问题是:Option崩溃到Some (Some x)

答案是否定的。崩溃会隐式更改类型,您将失去Some x提供的某些类型安全性。折叠和非折叠版本之间的区别可能很重要。举个例子。

Option

match List.tryHead [Some 1; None; Some 2] with | Some (Some x) -> sprintf "The first item exists with a value of %i" x | Some None -> "The first item exists but it has no value" | None -> "The list was empty" 函数返回列表的第一个元素,如果列表为空则返回None。我们将List.tryHead列表传递给它,以便返回Option<int>

我们能够匹配返回值以涵盖该返回类型的所有不同可能情况。如果您想以不同方式处理这些情况,这可能很有用。

但我们仍然可以将Option<Option<int>>Some None视为等效:

None

答案 2 :(得分:1)

不,您定义的选项类型不会自动合并到其他类型。它们是独立的歧视联盟,必须按此处理。

采用以下示例,该示例显示了如何模式匹配和构造Option2的值:

let info x = match x with
            | O (Some i) -> sprintf "Found %d" i
            | O (Option.None) -> "The wrapping Option2 contained None"
            | Option2.None -> "The wrapper was None"

System.Console.WriteLine(info (O (Some 3)))
System.Console.WriteLine(info (O Option.None))
System.Console.WriteLine(info Option2.None)

// prints:
// Found 3
// The wrapping Option2 contained None
// The wrapper was None