我正在使用一个简单的函数,该函数应该从类型为'a
的对象中提取'a option
的值。我在这里看到的示例看起来像我写的一样,但是OCaml对于使用'a option option
的函数感到困惑,我不确定为什么。
let extract_x x = match x with
| Some state -> state
| None -> None
utop中对OCaml的解释:val extract_x : 'a option option -> 'a option = <fun>
答案 0 :(得分:2)
假设我们是ocaml类型检查器(或更确切地说,是 an ),我们想确定您的值extract_x
let extract_x x = ...
好吧,在这里我们知道extract_x
的类型必须是函数_ -> _
。我们将其称为当前未知的输入类型a
和输出类型z
,然后变量x
的类型为a
:
extract_x : a -> z
x : a
... : z
让我们更深入地研究
let extract_x x = match x with
| p1 -> v1
| p2 -> v2
在这里,我已将模式和值命名为不编写它们。现在我们知道p1
和p2
必须匹配类型a
的值,并且v1
和v2
是类型z
。让我们看一下模式:
| Some state -> ...
| None -> ...
因此,现在我们可以推断出a
必须是某种option
。假设它是b option
。现在我们有:
extract_x : b option -> z
x : b option
... : z
(In first case only):
state : b
让我们看一下第一种情况:
| Some state -> state
因此,我们现在推断z = b
,即从该函数返回的类型是state
的类型,我们称为b
。让我们看看另一种情况:
| None -> None
该值(即->
之后的位)None
是一个选项类型。我们称其为c option
,我们也知道它必须为z
类型,所以让我们写下到目前为止的内容:
extract_x : a -> z
a = b option
z = b
z = c option
因此我们推论b = c option
如此a = c option option
,因此,将任意类型的变量标记为多态,我们得到:
extract_x : 'a option option -> 'a option
这是一个有用的功能(通常称为bind
),但不是您想要的功能。您可以按照以下方法编写类型为'a option -> 'a
的函数:
let extract_x x =
match x with
| Some x -> x
| None -> failwith "extract_x: expected Some"
但是,您可能根本不希望使用此功能,因为如果有选择,则可能是None
,这将引起此功能的提高,并且如果您选择的选项始终是{{ 1}},那么您应该尝试更改您的类型,以表明该内容不是可选的。否则,非法值Some
似乎是合法的,因为它可以被构造。
以下是您实际上如何以更安全的方式从选项中提取值的方法:
None
答案 1 :(得分:0)
参数x的类型为'a option option,因为extract_x返回None或state的值。这意味着“状态”本身必须是选项的变体。因此,作为选项(“某些状态”)进行模式匹配的x必须是选项的选项。
要解决此问题,您需要将模式匹配中的None情况评估为选项以外的其他类型,且类型与'state'相同。