F#将带参数的运算符传递给函数
-
08-07-2019 - |
题
你能传递像<!>一样的操作吗?除以2 <!>或<!> quot;减1 <!>仅使用部分应用的运算符,其中<!> quot; add 1 <!> quot;看起来像这样:
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)
,其中_
表示占位符,就像在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
可以这样做还是必须使用(fun x -> x/2)
?似乎我们最接近占位符语法的方法是使用带有命名参数的lambda。
解决方案
您可以编写一个翻转函数,例如:
let flip f x y = f y x
List.map (flip (-) 1) [2;4;6]
我的语法可能有误,我对F#不是很精通。
其他提示
F#,la Haskell中没有'操作部分',也没有占位符参数(显然是la Arc)。您可以使用另一个答案中建议的“翻转”组合器来反转参数的顺序,然后部分应用第一个(现在是第二个)参数。
但我会使用
fun x -> x / 2
除非你正在打代码高尔夫球,否则我不认为在这里试图刮掉另外几个角色会给你买任何东西。
Logan Capaldo 建议的 flip
-solution也可以使用运算符(此处为&gt;。
):
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]
修改:使用“看起来更像占位符”的运营商(这里&gt; - &lt;
)让您非常接近建议的语法:
List.map ((-) >-< 1) [2;4;6]
'_'不幸(?)没有 a F#中的有效运算符符号。