为什么Swift允许双重可选项?

4
当我看到可选项时,我首先想到的是它基本上是来自ml风格语言的Maybe monad。然而,一个真正的monad不应该双重包装东西(m(m(a)) == m(a))。在什么情况下,您希望有一个双重可选项而不是链接列表结构?
通过“双重可选项”,我指的是类型签名String??或类似的东西。在我的想法中,这应该自动转换为String?

5
可能相关:https://dev59.com/QF4d5IYBdhLWcg3wDvC0该问题涉及Swift中两个或多个可选项的使用。 - Martin R
我不同意最初的说法,即单子在任何情况下都应该被展平(或者我们应该如何理解它?)。拥有Optional<Optional<T>>是可以的,并且在需要时你可以展平它们(.flatMap()会这样做;有点像“绑定”)。 - werediver
1
@werediver 这不是一个观点,它是单子法则的一部分。虽然可以说可选项不应该是单子的,但我想问的是,在String?已经存在的情况下,String??有什么附加价值。 - Sam Schick
@SamSchick 我无法以这样的方式阅读单子定律。 - werediver
@dfd 询问更多理论问题的正确场所是什么?我知道这与实际无关,但我仍然很好奇。 - Sam Schick
显示剩余7条评论
1个回答

8

我将从Swift的角度来尝试回答这个问题,所以如果我的FP术语不正确,请原谅。

我何时会使用双重可选项?

有一个众所周知的情况需要使用双重可选项。当集合使用可选项来表示在此键上没有值,并且还存储可能是可选项的值时,知道是集合还是元素返回了nil可能很重要。

let possibleNumbers: [String: Int?] = [:]
guard let possibleNumber = possibleNumbers["one"] else {
     print("No number stored")
}
guard let number = possibleNumber else {
    print("Number at key was nil")
}

我们能否自动将T???????转换为T?

不行,但是可以使用flatMap实现。尽管你需要为每个可选级别添加一个新的映射。

possibleNumbers["one"].flatMap { $0 }

我不认为Swift中的Optional被明确地称为单子。它在内部实现为通用枚举类型,并且更紧密地遵循该类型的语义。至少我在语言指南https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html中找不到任何参考。请注意,HTML标签已保留。

1
我认为你说得对,它并没有明确地被称为单子,只是当我看到它被描述时,立刻想到了这个概念。我猜深度解嵌套的问题让我感到困扰,但你确实给出了一个使用案例。 - Sam Schick
非正式地说,有时在网上声称 Optional 是单子的。这里是一个著名的来源:http://chris.eidhof.nl/post/monads-in-swift/ 还值得注意的是,直接返回 Optional<Optional<Value>> 并不是查找的唯一解决方案。可以使用带外信号。例如,Python 字典可以包含 None,但 None 不能包装另一个值。因此,失败的查找会导致 "异常"(在 Python 中与 Swift 的用法非常不同)。这是一个很有争议的问题,哪个更不尴尬...@Sam - jscs
另一个出现这种情况的地方是迭代器。Swift 和 Python 实际上对此有非常相似的协议。不同之处在于,Swift 使用可选项(可能包装另一个可选项)来表示结束,而 Python 使用 StopIteration 异常。 - jscs

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接