Ocaml 提取原始数据';来自';选择权

Ocaml 提取原始数据';来自';选择权,ocaml,Ocaml,我正在使用一个简单的函数,该函数应该从类型为'a option的对象中提取'a的值。我在这里看到了一些类似于我所写的例子,但是对于一个使用选项的函数来说,OCaml把它搞混了,我不知道为什么 let extract_x x = match x with | Some state -> state | None -> None 在utop中可以看到OCaml的解释:val extract\u x:'a option option->'a option=参数x具有类型“a op

我正在使用一个简单的函数,该函数应该从类型为
'a option
的对象中提取
'a
的值。我在这里看到了一些类似于我所写的例子,但是对于一个使用选项的函数来说,OCaml把它搞混了,我不知道为什么

let extract_x x = match x with
  | Some state -> state
  | None -> None

在utop中可以看到OCaml的解释:
val extract\u x:'a option option->'a option=

参数x具有类型“a option option”,因为extract\u x返回None或状态值。这意味着“状态”本身必须是一个选项变量。因此,作为选项(“某些状态”)进行模式匹配的x必须是选项的选项


要解决这个问题,您需要在模式匹配中使用None case来计算除选项之外的其他内容,其类型与“state”相同。

让我们假设我们是(或者更确切地说,是)ocaml类型检查器,我们要确定您的值的类型
extract\x

let extract_x x = ...
好的,这里我们知道
extract\ux
的类型必须是一个函数,
\uu->\uu
。让我们调用当前未知的输入类型
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
一定是某种
选项。假设它是一个
b选项
。现在我们有:

extract_x : b option -> z
x : b option
... : z
(In first case only):
  state : b
让我们来看第一个案例:

  | Some state -> state
现在我们推断出
z=b
,也就是说,从这个函数返回的类型是
状态的类型,我们称之为
b
。让我们看看另一种情况:

  | None -> None
值(即
->
之后的位)
None
是一种选项类型。让我们称之为
c选项
,我们也知道这必须是
z类型
,所以让我们写下目前为止的情况:

extract_x : a -> z
a = b option
z = b
z = c option
因此,我们推断,
b=c选项
So
a=c选项
So,将任意类型变量标记为多态变量,我们得到:

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
,这将导致这个函数提升,如果您有一个总是
Some
的选项,那么您应该尝试更改您的类型,以表示这个东西不是可选的。否则,非法值
None
似乎是合法的,因为它可能是构造的

以下是您实际如何以更安全的方式处理从选项中提取值的问题:

...
match t.x with
| None -> failwith "invariant for foo violated in bar”
| Some x -> (* carry on *)
  ...

(* don’t do this *)
type 'a one_or_two = 'a option * 'a option
...
  let (first, second) = ... : _ one_or_two in
  match first with
  | None ->
    (* now we know second must be Some *)
    let second = extract_x second in
    ...

(* do this instead *)
type 'a one_or_two = First of 'a | Second of 'a | Both of 'a * 'a

这是因为
| None->None
。您希望
extract\u x
具有什么类型?输入具有type
state选项
type state=string
。它可以是
字符串
,也可以是
。返回值应该是原始的
状态
,不带
选项
关键字,或者如果输入是
,则返回值应该是
。我没有要求您提供散文描述。您希望
extract\u x
有什么类型?
extract\u x
应该有type
string
它不能有type
string
。字符串没有参数,无法调用;您的
extract_x
有一个
x
参数。