这是F#中的选项类型:
type Option<'a> =
| Some of 'a
| None
假设我有一个Option
的{{1}}:
Option
是否会折叠为只有一个type Option2<'a> =
| O of Option<'a>
| None
?
答案 0 :(得分:5)
不,F#有名义类型系统。 结构等效类型不兼容。因此,即使您Option
和Option2
完全相同(名称除外),这些类型也会有所不同。您的情况不同,类似于询问整数列表和整数列表是否相同。
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