从'a选项中提取原始'a变量

时间:2019-02-09 16:29:27

标签: ocaml

我正在使用一个简单的函数,该函数应该从类型为'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>

2 个答案:

答案 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

在这里,我已将模式和值命名为不编写它们。现在我们知道p1p2必须匹配类型a的值,并且v1v2是类型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'相同。