F#:实际上,“字符串”和“字符串选项”之间有什么区别?

时间:2009-06-03 22:53:05

标签: f#

实际上,“字符串”和“字符串选项”之间有什么区别?

除了轻微的sytnax问题,我看到的唯一区别是你可以将“null”传递给字符串,而字符串选项需要“none”。

2 个答案:

答案 0 :(得分:28)

我并不特别喜欢我在下面输入的答案,因为我认为读者会将其视为“向合唱团讲道”或“某些复杂的废话”,但我决定发布它无论如何,如果它邀请富有成效的评论讨论。

首先,理解

可能值得注意
let x : string option = Some(null)

是一个有效值,表示值的存在(而不是不存在)(Some而不是None),但值本身为null。 (这种价值的含义取决于背景。)

如果您正在寻找我认为的“正确”心理模型,那就是这样......

“所有引用类型都承认'null'值”的整个概念是.Net和CLR最大和最昂贵的错误之一。如果平台今天从头开始重新设计,我想大多数人都同意默认情况下引用是不可为空的,并且你需要一个明确的机制来选择加入null。就目前而言,有数百个,如果不是数千个API,例如“string foo”并且不想要null(例如,如果传递null则会抛出ArgumentNullException)。显然,这是类型系统更好地处理的事情。理想情况下,'string'表示'非null',对于 少数,你可以拼写出来,例如“Nullable< string> foo”或“Option< string> foo”或其他。所以现有的.Net平台就是这里的'古怪'。

许多函数式语言(例如ML,F#的主要影响之一)已经永远知道这一点,因此设计了他们的类型系统“正确”,如果你想承认'null'值,你使用泛型类型构造函数,用于显式地发出有意识地将“值的值”作为合法值的数据。在ML中,这是通过“'t选项”类型完成的 - “选项”是一个很好的通用解决方案。 F#的核心是与ML方言OCaml兼容(交叉编译),因此F#从其ML系列继承了这种类型。

但是F#也需要与CLR集成,而在CLR中,所有引用都可以为null。 F#尝试走一条细线,因为你可以在F#中定义新的类类型,对于那些类型,F#将表现为类似ML(并且不容易将null作为值):

type MyClass() = class end
let mc : MyClass = null  // does not compile

但是,在C#程序集中定义的相同类型将允许null作为F#中的正确值。 (而F#仍然允许后门:

let mc : MyClass = Unchecked.defaultof<_> // mc is null

有效绕过普通的F#类型系统并直接访问CLR。)

这一切都开始听起来很复杂,但基本上F#系统让你可以用'ML'风格编写大量的F#,你永远不需要担心null / NullReferenceExceptions,因为类型系统阻止你做这里错了。但是F#必须很好地与.Net集成,所以所有源自非F#代码的类型(比如'string')仍然允许空值,因此当使用这些类型进行编程时,你仍然需要像通常那样进行防御性编程。 CLR。关于null,有效的F#提供了一个避风港,可以很容易地进行“无空编程,上帝的意图”,但同时与.Net的其余部分进行互操作。

我还没有真正回答你的问题,但是如果你遵循我的逻辑,那么你就不会问这个问题(或者不会问它,来自“Godel,Escher,Bach”的Joshu的MU)。

答案 1 :(得分:4)

我认为您可以将其重新归类为更一般的问题

  

选项随机引用类型和随机引用类型

之间有什么区别

与选项不同的是,您提供了一个明确的空值案例。这是一种说法“我可能不提供价值”的宣称方式。值选项无明确表示缺少值。

人们常常使用null来表示缺少值。不幸的是,这对于随意读者来说是不明确的,因为不知道null是表示有效值还是缺少值。选项消除了这种歧义。