【问题标题】:How to implement the list filter function in F# using primitives如何使用原语在 F# 中实现列表过滤功能
【发布时间】:2012-08-03 17:04:07
【问题描述】:

我正在阅读Why functional programming matters,其中作者使用 foldr 和函数组合实现了几个应用程序。我在 F# 中做了其中的一些,例如地图功能:

let cons a lst = a::lst
let map f lst = List.foldBack (f>>cons) lst []

然后我想实现列表过滤功能,结果卡住了:

let filter pred lst = List.foldBack (what-goes-here?) lst []

what-goes-here? 函数应该将列表项、累积过滤列表作为输入,如果谓词返回 false,则返回相同的列表,如果返回 true,则返回 cons:ed 列表.

我想我在这里需要选项类型,但不知道如何将它们粘合在一起。 是否可以使用 pred 和 cons(可能还有其他一些原语)来编写一个函数来实现这个而不编写一个自定义的 lambda 函数来完成所有的工作?这是计算表达式的情况吗?

【问题讨论】:

  • 不写 lambda 有什么意义?毫无意义,原谅,无意义的风格?这显然适用于纯代码:fun x xs -> if f x then x :: xs else xs。请注意,它与 List.filter 的不同之处在于存在副作用,List.foldBack 则不合适。
  • 谢谢。关键是我想了解更多关于 fp 的一般知识,在这种情况下是函数组合。为什么它与 List.filter 存在副作用不同?
  • @Christian:因为您正在反向遍历列表 (foldBack),所以您的副作用将以相反的顺序发生。 (例如,打印列表)
  • @Christian - 它非常隐蔽 - github.com/fsharp/fsharp/blob/master/src/fsharp/FSharp.Core/… 在第 163 行
  • @bytebuster,也许您描述的属性是linear(如linear logic),而不是monadic。无论如何,你的说法是不正确的。给定一个合适的基,例如 SKI 基,可以在没有 lambda 绑定器的情况下表达这个函数。

标签: f# functional-programming pointfree


【解决方案1】:

您的问题的务实答案是:

whatGoesHere = fun x xs -> if f x then x :: xs else xs

匿名函数、if-then-else 和列表都被考虑 F# 从业者的原语。这是最清楚最 编写此代码的可维护方式。

唉,您还没有接受来自 以前的响应者,而您坚持看到不涉及的代码 拉姆达表达式。不客气:

``s``s`ks``s`k`s`ks``s``s`ks``s`k`s`ks``s`k`s`kk``s
`k`s`k``s``s`ks``s`k`s`ks``s`k`s`kk``s``s`ks``s`kki
`ki`k`ki``s``s`ks``s`kki`ki
`k``s``s`ks``s`kk``s`k``s``s`ks``s`kk``s`ks``s`k`s`ks
``s`k`s`kk``s`k`si``s`kki`k``s``s`ks
``s`k`s`ks``s`k`s`kk``s``s`ks``s`kki`ki
`k`kii`ki`k`ki

上面是whatGoesHere 在 SKI 组合演算中使用合适的 布尔值和列表的表示形式,以 Unlambda 表示法打印。

为方便起见,这里有一个来自 untyped 的示例编译器 SKI 组合子的 lambda 演算,以及 lambda 的 F# 定义 与您的问题相对应的微积分术语:

http://gist.github.com/3277850

虽然组合逻辑和 lambda 演算的等价性 使 lambda 表达式在理论上是不必要的,它们是不可或缺的 用于表达您作为程序员的意图。 “为什么函数式编程很重要” 绝不提倡避免 lambda 表达式和辅助函数。 相反 - 定义功能的能力,包括 高阶函数,是函数式编程的核心。 函数是由组合定义还是由组合定义无关紧要 明确使用 lambda 演算:两者都是“粘合剂” 论文谈到了。

我建议你给论文(也许还有它的优秀参考) 再读一遍,然后安装 Haskell 或 Clean。鉴于作者 提倡纯lazy-by-default评估模型,F#不好 探索这些想法的平台。

【讨论】:

  • 谢谢你,我的思路开阔了! :) 作为记录:我不是要抨击 lambdas 或条件,我只是好奇是否有可能,根据“为什么函数式编程很重要”中的粘合示例,对 filter-function 做同样的事情.在现实世界的情况下,我当然会选择最实用和可维护的解决方案。
【解决方案2】:
let consT pred a lst = if pred a then a::lst else lst
let filter pred lst = List.foldBack (consT pred) lst []

【讨论】:

  • 谢谢,但这不是我想要的。我一直在寻找一种解决方案,其中只使用原始组合函数而不是自定义编写函数。
  • (consT pred) 等原始函数不是。
猜你喜欢
  • 2019-09-05
  • 2019-05-10
  • 1970-01-01
  • 1970-01-01
  • 2010-12-18
  • 1970-01-01
  • 2014-05-02
  • 2018-12-15
  • 2015-06-15
相关资源
最近更新 更多