F# 将带有参数的运算符传递给函数

发布于 2024-08-13 02:47:54 字数 1147 浏览 1 评论 0原文

您可以仅使用部分应用运算符传递“除以 2”或“减 1”等操作,其中“加 1”如下所示:

List.map ((+) 1) [1..5];;  //equals [2..6]
// instead of having to write: List.map (fun x-> x+1) [1..5]

发生的情况是 1 被应用到 (+) 作为它的第一个参数,并且列表项被用作第二个参数。对于加法和乘法,此参数顺序并不重要。

假设我想从每个元素中减去 1(这可能是初学者常见的错误):

List.map ((-) 1) [1..5];;  //equals [0 .. -4], the opposite of what we wanted

1 应用于 (-) 作为其第一个参数,因此我不是 (list_item - 1),而是获取(1 - list_item)。我可以将其重写为加负数而不是减去正数:

List.map ((+) -1) [1..5];;
List.map (fun x -> x-1) [1..5];; // this works too

我正在寻找一种更具表现力的编写方式,例如 ((-) _ 1),其中 _< /code> 表示占位符,就像在 Arc 语言中一样。这将导致 1 成为 - 的第二个参数,因此在 List.map 中,它将计算为 list_item - 1。因此,如果您想将 divide by 2 映射到列表,您可以编写:

List.map ((/) _ 2) [2;4;6] //not real syntax, but would equal [1;2;3] 
List.map (fun x -> x/2) [2;4;6] //real syntax equivalent of the above

Can this be done or do I have to use (fun x -> x/2)?看起来我们能得到的最接近占位符语法的方法是使用带有命名参数的 lambda。

Can you pass in an operation like "divide by 2" or "subtract 1" using just a partially applied operator, where "add 1" looks like this:

List.map ((+) 1) [1..5];;  //equals [2..6]
// instead of having to write: List.map (fun x-> x+1) [1..5]

What's happening is 1 is being applied to (+) as it's first argument, and the list item is being applied as the second argument. For addition and multiplication, this argument ordering doesn't matter.

Suppose I want to subtract 1 from every element (this will probably be a common beginners mistake):

List.map ((-) 1) [1..5];;  //equals [0 .. -4], the opposite of what we wanted

1 is applied to the (-) as its first argument, so instead of (list_item - 1), I get (1 - list_item). I can rewrite it as adding negative one instead of subtracting positive one:

List.map ((+) -1) [1..5];;
List.map (fun x -> x-1) [1..5];; // this works too

I'm looking for a more expressive way to write it, something like ((-) _ 1), where _ denotes a placeholder, like in the Arc language. This would cause 1 to be the second argument to -, so in List.map, it would evaluate to list_item - 1. So if you wanted to map divide by 2 to the list, you could write:

List.map ((/) _ 2) [2;4;6] //not real syntax, but would equal [1;2;3] 
List.map (fun x -> x/2) [2;4;6] //real syntax equivalent of the above

Can this be done or do I have to use (fun x -> x/2)? It seems that the closest we can get to the placeholder syntax is to use a lambda with a named argument.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

我三岁 2024-08-20 02:47:54

您可以编写一个翻转函数,例如:

let flip f x y = f y x

List.map (flip (-) 1) [2;4;6]

我可能语法错误,我对 F# 不太流利。

You could write a flip function, something like:

let flip f x y = f y x

List.map (flip (-) 1) [2;4;6]

I may have the syntax wrong, I'm not terribly fluent in F#.

夏末 2024-08-20 02:47:54

F# 中没有像 Haskell 那样的“操作部分”,也没有占位符参数(显然是像 Arc 那样)。您可以按照另一个答案中的建议使用“翻转”组合器来反转参数的顺序,然后部分应用第一个(现在是第二个)参数。

但我只会使用

fun x -> x / 2

除非你正在玩代码高尔夫,否则我认为尝试在这里删除另外几个字符不会给你带来任何好处。

There are no 'operation sections' in F#, a la Haskell, nor placeholder arguments (apparently a la Arc). You can use a 'flip' combinator as suggested in another answer to reverse the order of arguments and then partially apply the first (now second) argument.

But I would just use

fun x -> x / 2

Unless you're playing code-golf, I don't think trying to shave another few characters off here buys you anything.

不忘初心 2024-08-20 02:47:54

Logan Capaldo 建议的 flip 解决方案也可以使用运算符编写(此处>.):

let (>.) x f = (fun y -> f y x)
List.map (1 >. (-)) [2;4;6]

或者如果您更喜欢相反的操作数:

let (>.) f x = (fun y -> f y x)
List.map ((-) >. 1) [2;4;6]

编辑: 使用“看起来更像占位符”的运算符(此处 > -<) 让您非常接近建议的语法:

List.map ((-) >-< 1) [2;4;6]

不幸的是,'_' 不是 F# 中的有效运算符符号

The flip-solution suggested by Logan Capaldo can also be written using a operator (here >.):

let (>.) x f = (fun y -> f y x)
List.map (1 >. (-)) [2;4;6]

Or if you prefer the operands the other way around:

let (>.) f x = (fun y -> f y x)
List.map ((-) >. 1) [2;4;6]

Edit: Using an operator that "looks more like a placeholder" (here >-<) gets you very close to your suggested syntax:

List.map ((-) >-< 1) [2;4;6]

'_' is unfortunatly(?) not a valid operator symbol in F#.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文