当输入为 None 时,函数的名称类似于 Option.bind that returns Some(x)
Name for function like Option.bind that returns Some(x) when input is None
普通的Option.bind
函数是这样定义的:
// ('T -> 'U option) -> 'T option -> 'U option
let bind f x =
match x with
| None -> None
| Some x' -> f x'
我需要一个稍微不同的版本:
// ('T -> 'U -> 'U option) -> 'T option -> ('U -> 'U option)
let myBind f x =
match x with
| None -> Some
| Some x' -> f x'
这个函数有标准名称吗?(如果没有,我很乐意接受简洁的建议。)
对于感兴趣的读者,我的用例是这样的:我有一个业务对象(比如 Order
),我想对(订单日期、客户等)应用约束。应用约束的功能,例如Order
有签名 'Constraint -> Order -> Order option
。如果订单通过约束,它们 return Some order
,否则 None
(因此可以使用 Option.bind
组合)。现在,如果约束是 None
,它本质上是一个空操作,Some order
应该是 returned。我可以使用上面的函数分解出这部分逻辑,而不是让所有约束函数都接受 'Constraint option
(然后需要在组合过程中应用)。
我最初将该函数称为 bindConstraint
,但它完全是通用的,与我的用例无关(参考 Mark Seemann 的 article on the topic)。由于它与 bind
相似,我想知道是否有一个标准名称。
让我们看看您的函数类型签名:
// ('T -> 'U -> 'U option) -> 'T option -> ('U -> 'U option)
'U -> 'U option
类型实际上可以从该签名中提取出来。我们称该类型为 'V
。那么类型签名就变成了:
// ('T -> 'V) -> 'T option -> 'V
看起来很像Option.map
,签名是:
// ('T -> 'V) -> 'T option -> 'V option
所以基本上,您的函数等效于 Option.map
后跟 defaultArg
将 'V option
变成 'V
(如果选项是,则提供默认值None
).
所以我可能会称它为 defaultMap
或 mapDefault
。
嗯...
我想知道你是否排除了 'U,你最终在 reader monad 中工作,然后你的函数是 option.bind 无事可做!
'U -> .....('T -> 'U 选项) -> 'T 选项 -> 'U 选项
即这是对字符串的约束?
let longerThan : int -> string -> string option =
fun i s ->
if (String.length s > i) then
Some s
else
None
这是你在使用 myBind
let foo = myBind longerThan (Some 1)
但这是没有 myBind 的代码
let bar =
fun s ->
(Some 1) |> Option.bind (fun i -> longerThan i s)
我们刚刚分解出 'U 并且我们在函数中编写代码。
(我的代码看起来更复杂,因为我们编写的时间比与您的绑定更好地配合使用的时间更长,如果我们交换参数顺序,那么您的版本看起来比我的更复杂)
我的另一个观察是,如果你只是在做约束,那么就不会使用
'U -> 布尔值
更简单一点?...然后您只需使用 "where"...(您可以在计算表达式中执行此操作吗?...我认为您可以在 LINQ 中执行)。
P.S.
实际上你的代码的语义是不同的...你希望 None 被解释为恒等映射....
所以实际上我认为在你的世界里我会直接对约束进行操作
type Constraint<'a> = 'a -> 'a option
let applyConstraint : Constraint<'a> option -> 'a -> 'a option =
function
| None -> Some
| Some f -> f
然后简单地组合约束;
let compose : Constraint<'a> -> Constraint<'a> -> Constraint<'a> =
fun c1 c2 -> fun a -> Option.bind c2 (c1 a)
(虽然我可能把 c1 和 c2 搞错了)
普通的Option.bind
函数是这样定义的:
// ('T -> 'U option) -> 'T option -> 'U option
let bind f x =
match x with
| None -> None
| Some x' -> f x'
我需要一个稍微不同的版本:
// ('T -> 'U -> 'U option) -> 'T option -> ('U -> 'U option)
let myBind f x =
match x with
| None -> Some
| Some x' -> f x'
这个函数有标准名称吗?(如果没有,我很乐意接受简洁的建议。)
对于感兴趣的读者,我的用例是这样的:我有一个业务对象(比如 Order
),我想对(订单日期、客户等)应用约束。应用约束的功能,例如Order
有签名 'Constraint -> Order -> Order option
。如果订单通过约束,它们 return Some order
,否则 None
(因此可以使用 Option.bind
组合)。现在,如果约束是 None
,它本质上是一个空操作,Some order
应该是 returned。我可以使用上面的函数分解出这部分逻辑,而不是让所有约束函数都接受 'Constraint option
(然后需要在组合过程中应用)。
我最初将该函数称为 bindConstraint
,但它完全是通用的,与我的用例无关(参考 Mark Seemann 的 article on the topic)。由于它与 bind
相似,我想知道是否有一个标准名称。
让我们看看您的函数类型签名:
// ('T -> 'U -> 'U option) -> 'T option -> ('U -> 'U option)
'U -> 'U option
类型实际上可以从该签名中提取出来。我们称该类型为 'V
。那么类型签名就变成了:
// ('T -> 'V) -> 'T option -> 'V
看起来很像Option.map
,签名是:
// ('T -> 'V) -> 'T option -> 'V option
所以基本上,您的函数等效于 Option.map
后跟 defaultArg
将 'V option
变成 'V
(如果选项是,则提供默认值None
).
所以我可能会称它为 defaultMap
或 mapDefault
。
嗯...
我想知道你是否排除了 'U,你最终在 reader monad 中工作,然后你的函数是 option.bind 无事可做!
'U -> .....('T -> 'U 选项) -> 'T 选项 -> 'U 选项
即这是对字符串的约束?
let longerThan : int -> string -> string option =
fun i s ->
if (String.length s > i) then
Some s
else
None
这是你在使用 myBind
let foo = myBind longerThan (Some 1)
但这是没有 myBind 的代码
let bar =
fun s ->
(Some 1) |> Option.bind (fun i -> longerThan i s)
我们刚刚分解出 'U 并且我们在函数中编写代码。
(我的代码看起来更复杂,因为我们编写的时间比与您的绑定更好地配合使用的时间更长,如果我们交换参数顺序,那么您的版本看起来比我的更复杂)
我的另一个观察是,如果你只是在做约束,那么就不会使用
'U -> 布尔值
更简单一点?...然后您只需使用 "where"...(您可以在计算表达式中执行此操作吗?...我认为您可以在 LINQ 中执行)。
P.S.
实际上你的代码的语义是不同的...你希望 None 被解释为恒等映射....
所以实际上我认为在你的世界里我会直接对约束进行操作
type Constraint<'a> = 'a -> 'a option
let applyConstraint : Constraint<'a> option -> 'a -> 'a option =
function
| None -> Some
| Some f -> f
然后简单地组合约束;
let compose : Constraint<'a> -> Constraint<'a> -> Constraint<'a> =
fun c1 c2 -> fun a -> Option.bind c2 (c1 a)
(虽然我可能把 c1 和 c2 搞错了)