F# 过滤器函数 - 第一个参数的条件似乎颠倒了

标签 f# functional-programming

我今天对 F# 过滤器功能有一点奇怪的体验。代码是:

let rec filter : ('a -> bool) -> 'a list -> 'a list =
    fun isKept -> function
        | [] -> []
        | (x::xs) -> if isKept x then x::filter isKept xs
                     else filter isKept xs

let x = filter ((>) 1) [1; -5; -20; 30; -35; 40]

该代码返回
val x : int list = [-5; -20; -35]

问题是,当我在第一个参数 (> 1) 中传递一个条件时,我希望它会过滤掉第二个参数中大于 1 的任何列表元素,而不是相反。

有什么明显我看不到的东西吗?

最佳答案

你的过滤功能很好。问题是这行代码:

let x = filter ((>) 1) [1; -5; -20; 30; -35; 40]

如果您使用显式 lambda 而不是部分应用 (>),则等效于此代码运算符(operator):
let x = filter (fun x -> 1 > x) [1; -5; -20; 30; -35; 40]

造成这种情况的原因是 (>)函数接受两个参数;即使 1出现在 (>) 的右侧,它不会作为“正确”参数传递给函数。解决方案是使用 (<)反而:
> let x = filter ((<) 1) [1; -5; -20; 30; -35; 40];;

val x : int list = [30; 40]

或者使用显式 lambda 函数来确保您以正确的顺序应用参数:
> let x = filter (fun x -> x > 1) [1; -5; -20; 30; -35; 40];;

val x : int list = [30; 40]

关于F# 过滤器函数 - 第一个参数的条件似乎颠倒了,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18673632/

相关文章:

javascript - 柯里化(Currying)一个接受无限参数的函数

构造函数中带有参数的 Java 8 供应商

f# - 用 F# 编写符合 CLS 的代码

f# - 是否可以在 f# 中使用 CallerMemberNameAttribute

azure - 为什么 Microsoft Identity Web API 中间件拒绝对访问 token 进行身份验证?

string - 如何在Elixir中循环遍历字符串中的每个字符?

java - 仅过滤掉列表中与某些元素匹配的第一个元素的替代方法

c# - C#项目中的F#类型扩展:是否缺少System.Runtime.CompilerServices.Extension?

f# - 受歧视的工会结构/习俗平等

f# - 由于循环引用,确定如何订购 F# 类型的问题