I have the following code:
let f g x = if x < 0 then None else Some(g x)
除了 f
函数可能或可能不返回 Option
之外,g
函数也是如此。由于 f
是通用的,并且没有任何通用约束,因此我最终可能会得到 Some(Some(z))
的结果。事实上,我只想要 None
或 Some(z)
中的一个。我该如何避免双重包装(最好不对 g
强加约束)?
I have the following code:
let f g x = if x < 0 then None else Some(g x)
除了 f
函数可能或可能不返回 Option
之外,g
函数也是如此。由于 f
是通用的,并且没有任何通用约束,因此我最终可能会得到 Some(Some(z))
的结果。事实上,我只想要 None
或 Some(z)
中的一个。我该如何避免双重包装(最好不对 g
强加约束)?
> let f g x = if x < 0 then None else Some(g x)
val f : g:(int -> 'a) -> x:int -> 'a option
f
返回'a option
,这意味着它可以返回Some z
或Some (Some y)
等。 f
可以使用任意数量的嵌套Some
返回结果,具体取决于g
的类型。
Some
合并的函数。它可以手动编写:let collapseOptions x =
match x with
| Some (Some y) -> y
| _ -> None
Some
函数,我希望看到它的签名 :)g
的类型设为'a -> Option<'b>
,要么单独处理嵌套的选项值。第一个版本:let f (g: int -> Option<'b>) (x: int) =
if x < 0 then None else g x
int -> 'b
的普通函数传递给f
时,您需要将它提升为类型为int -> Option<int>
的函数。以下是一个示例:// Simple function of type: int -> int
let plusOne = (+) 1
let y = f x (pluseOne >> Some)
let f (g: int -> 'b) (x: int) = if x < 0 then None else Some (g x)
如果需要的话,可以简单地折叠结果。这可以通过Option.bind id
轻松实现,如下所示:
// This function has type: int -> Option<int>
let posPlusOne n = if n < 0 then None else Some (n + 1)
let y = f x posPlusOne |> Option.bind id
g
返回 Option 'a
,而 bind g (Some x)
就是 g x
。 - ДМИТРИЙ МАЛИКОВlet f g x =
maybe {
if x<0 then None
else
let! gx = g x
return f gx }
if x < 0 then
None
else match g x with
|Some(t) -> Some(t)
|None -> None
else g x
而没有更多的操作来解决原问题 :) - ДМИТРИЙ МАЛИКОВg
返回Option 'a
,虽然在某些情况下这可能是一种解决方案,但似乎会增加不必要的复杂性,因为只有一个接受 Option 'a
的函数可以用作g
。 我的意思是,如果我想使用一个接受直接'a
的函数g'
,那么我必须将其包装成let g x = Some(g' x)
的形式。 - Trident D'Gao