【发布时间】:2016-02-21 18:02:57
【问题描述】:
我很喜欢使用管道运算符'|>'。但是,当将返回“简单”值的函数与返回“选项类型值”的函数混合使用时,事情会变得有点混乱,例如:
// foo: int -> int*int
// bar: int*int -> bool
let f (x: string) = x |> int |> foo |> bar
有效,但它可能会抛出“System.FormatException:...”
现在假设我想通过让函数 'int' 给出一个可选结果来解决这个问题:
let intOption x =
match System.Int32.TryParse x with
| (true, x) -> Some x
| (false,_) -> None
现在唯一的问题当然是功能
let g x = x |> intOption |> foo |> bar
由于输入错误而无法编译。好的,只需定义一个“可选”管道:
let ( |= ) x f =
match x with
| Some y -> Some (f y)
| None -> None
现在我可以简单地定义:
let f x = x |> intOption |= foo |= bar
一切都像魅力一样。
好的,问题:那是惯用的 F# 吗?可以接受吗?风格不好?
备注:当然,如果类型正确,'|=' 运算符允许随意拆分和合并'管道'与选项,同时只关心重要的选项:
x |> ...|> divisionOption |= (fun y -> y*y) |=...|>...
【问题讨论】:
-
我不认为需要这个操作符,因为你可以使用
|> Option.map f- 事实上你可以定义你的操作符;) - 最好是使用|> Option.bind f你得到单子案例也是如此;) -
在使用管道运算符时没有什么特别“惯用的”,除了它有时有助于类型推断。滥用它(以及任何其他自定义运算符)可能会大大降低代码的可读性。
-
哦,是的,没想到 Option.map。所以我想这可以回答所有问题;有一个核心库函数,我的操作符或多或少是一个特例,因此使用 inbuild 函数当然更好......thx