是否有将多个管道转换为功能组合的分步过程?
旁注:
我什至在正确的上下文中使用了术语“功能组合”吗?
我有以下代码:
let purchase qty inventory =
buyFrom inventory qty |> fromInventory
|> reduceBy qty
我想重构此代码以支持功能组合。
所以我想我可以这样做:
let purchase qty inventory =
buyFrom inventory >> fromInventory >> reduceBy qty
此代码编译。但是,在尝试在调试器中调用购买函数时,我似乎缺少一个参数。
这是我对该功能的测试:
[<Test>]
let ``buy last product``() =
[SomeProduct] |> purchase 1
|> should equal []
注意:
我仍在为 FP 基础而苦苦挣扎,并且仍然不了解将管道工作流转换为功能组合的过程。
我想我明白功能组合依赖于部分应用程序,我想我现在已经掌握了。因此,我有理由相信我的重构函数缺少一个参数。
关于我可以用来更好地进行功能组合的工作流程的任何指导?
附录:
type Product =
| SomeProduct
type TransactionResult = { Price:decimal; Inventory:Product list }
(* Functions *)
let priceOf qty product =
match product with
| SomeProduct -> match qty with
| 3 -> decimal (qty - 1) * 1.99m
| _ -> decimal (qty) * 1.99m
let rec reduceBy count list =
match list with
| first::remaining when count = 1 -> remaining
| first::second::remaining when count > 1 -> second::remaining |> reduceBy (count - 1)
| remaining when count = 0 -> remaining
| _ -> []
let buyFrom inventory qty =
{ Price=priceOf qty (List.head inventory); Inventory=inventory }
let fromInventory transactionResult =
transactionResult.Inventory
最佳答案
直接翻译为组合形式将是:
使用“转发”函数组合:
let purchase qty inventory = (buyFrom inventory >> fromInventory >> reduceBy qty) qty
使用“向后”函数组合(就个人而言,我不确定我喜欢术语“向后”,因为这是该术语传统数学意义上的函数组合,即
f << g = f ∘ g
):let purchase' qty inventory = reduceBy qty << fromInventory << buyFrom inventory <| qty
从上面的示例中您或许可以看出,当它让您完全跳过最后一个参数时,它确实最有值(value)。在这个例子中,你不能这样做,因为你依赖于
qty
两次所以我建议你在这里坚持使用管道。一般来说,如果你有一个函数
f(x)
和一个函数 g(x)
你可以写一个组合函数h(x) = (f ∘ g)(x)
通过以下方式:let h x = f (g (x))
let h x = x |> g |> f
let h x = f << g <| x
let h x = (g >> f) x
后两种情况,使用函数组合,可以省略
x
完全。let h = f << g
let h = g >> f
关于f# - 是否有将一系列管道转换为功能组合的分步过程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38504899/