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