【问题标题】:Reversing partial function parameters sequence反转部分函数参数序列
【发布时间】:2022-07-11 00:25:10
【问题描述】:

我想写 将List.map (fun x -> x % 3) 转换为List.map ((%) 3) 之类的形式。
后者的问题在于它转换为
List.map (fun x -> 3 % x) 不是我想要的

是否可以更简洁地写List.map (fun x -> x % 3).

更多背景
F# 的新手。发现能够使用部分应用程序编写简洁的表达式真是太好了。

例如对于逻辑add 3 to each item in list 可以写成List.map ((+) 3)

但是,这不适用于对位置敏感的操作,例如除法和模数。
例如。我将List.map ((/) 3) 读为 - 对于列表中的每个项目,除以 3。
但实际的逻辑其实是映射3分每一项。

[12; 24; 36; 48] |> List.map ((/) 3)
// expect [4; 8; 12; 16]
// actual [3/12; 3/24; 3/36; 3/48] // type discrepancy. but just an example.

根据JL0PD 的回答,我认为我想要的对于 F# 是不可能的(目前)。


回顾

由于柯里化/参数定位的性质,我想要的不可行。例如。
(/) 12 3 = 12 / 3  // left hand op and right hand op are equivalent.
// val it: bool = true

【问题讨论】:

  • 使用镜头的有趣示例。也许它会允许你做你想做的事haskellforall.com/2013/05/…
  • @JLOPD 的答案是最好的方法,并且在 Haskell 和非正式的 F# 中长期使用,因为您必须自己定义 flip。以后不会有别的了。一个悬而未决的问题是为什么flip 不是该语言的正式部分。
  • @MartinFreedman,Don Syme,F# 的作者,多次发言F# code I love。他解释了语言设计背后的许多决定。作为“为什么”的另一个来源,history of F#,对 F# 历史、影响和设计的 58 页反思
  • 是的,我对这一切都很熟悉。将flip 添加到几乎f# 项目中只是一种痛苦。我同意他对<| 的大部分推理,并且没有将>|<| 放在一行中,但flip 解决了这个问题。

标签: f# currying partial-application


【解决方案1】:

对于具有不正确参数顺序的函数的常见解决方法是flip函数

let flip f x y = f y x

用这个函数你可以写

List.map (flip (%) 3)

不太通用,但更明确的是创建专门的函数,如mod

let mod y x = x % y
List.map (mod 3)

但我认为这不会增加可读性和/或可维护性。我会改用当前版本

【讨论】:

  • 我不会说这是一个 incorrect 的参数顺序,只是不是手头案例所需的顺序。这是函数式编程中的一个常见问题,因此需要一个函数来反转参数。
【解决方案2】:

我完全同意 JL0PD 的回答。 另一种选择是您可以定义自己的运算符。 即

let (%.) x y = y % x 
[12; 24; 36; 48] |> List.map ((%.) 3)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多