【问题标题】:How do you design a functional program? [closed]你如何设计一个功能程序? [关闭]
【发布时间】:2010-09-16 13:34:27
【问题描述】:

从我编程生涯的第一天开始,我就开始使用面向对象编程。但是,我对学习其他范式很感兴趣(我在 SO 上说过很多次的事情是一件好事,但我没有时间去做)。我想我不仅准备好了,而且有时间,所以我将开始使用 F# 进行函数式编程。

但是,我不确定如何构建更少的设计应用程序。我习惯了 OO 编程中的每个文件一个类和类名词/功能动词的想法。您如何设计和构建功能性应用程序?

【问题讨论】:

    标签: f# functional-programming


    【解决方案1】:

    这完全是关于纯函数以及如何组合它们以构建更大的抽象。这实际上是一个难题,需要robust mathematical background。幸运的是,有几种模式可以进行深入的正式和实践研究。在Functional and Reactive Domain ModelingDebasish Ghosh 上进一步探讨了这个主题,并结合了几个应用纯函数模式的实际场景:

    函数式和反应式领域建模教你如何思考 纯函数方面的领域模型以及如何将它们组合成 构建更大的抽象。您将从以下基础开始 函数式编程并逐渐向高级概念发展 以及实现复杂领域模型所需了解的模式。 这本书演示了高级 FP 模式如何像代数数据 类型、基于类型类的设计和副作用的隔离可以使 你的模型是为了可读性和可验证性而编写的。

    【讨论】:

      【解决方案2】:

      关于构建功能程序:

      虽然 OO 语言使用类构建代码,但函数式语言使用模块构建代码。对象包含状态和方法,模块包含数据类型和函数。在这两种情况下,结构单元将数据类型与相关行为组合在一起。两种范式都有用于构建和实施抽象障碍的工具。

      我强烈建议您选择一种您熟悉的函数式编程语言(F#、OCaml、Haskell 或 Scheme),并仔细研究其标准库的结构。

      例如,将 OCaml Stack 模块与 .NET 中的 System.Collections.Generic.Stack 或 Java 中的类似集合进行比较。

      【讨论】:

      • 对象不一定包含状态。以 OCaml 中的功能对象更新为例。
      【解决方案3】:

      F# 为大规模结构化编程(例如接口)提供了传统的 OO 方法,并没有尝试提供 OCaml 等语言中首创的实验性方法(例如函子)。

      因此,F# 程序的大规模结构化与 C# 程序基本相同。

      【讨论】:

        【解决方案4】:

        How to Design Programs 就是这样(冗长乏味,使用 Scheme 而不是 F#,但原则延续)。简而言之,您的代码反映了您的数据类型;这个想法可以追溯到老式的“结构化编程”,只有函数式编程更明确,并且具有更高级的数据类型。

        【讨论】:

          【解决方案5】:

          您可能想查看我最近的一篇博客文章:How does functional programming affect the structure of your code?

          在较高层次上,OO 设计方法对于构建 F# 程序仍然非常有用,但是当您深入到较低层次时,您会发现这种方法被打破(规则的更多例外)。在物理层面上,“每个文件一个类”并非在所有情况下都有效,因为需要在同一个文件中定义相互递归的类型(type Class1 = ... and Class2 = ...),并且您的一些代码可能驻留在未绑定到特定类的“免费”函数中(这是 F#“模块”的优点)。 F# 中的文件排序约束也将迫使您批判性地思考程序中类型之间的依赖关系;这是一把双刃剑,因为解开高级依赖关系可能需要更多的工作/思考,但会产生以始终使它们易于接近的方式组织的程序(因为最原始的实体总是排在第一位,你可以总是从“从上到下”阅读程序并逐一介绍新事物,而不是仅仅开始寻找一个充满代码文件的目录而不知道“从哪里开始”。

          【讨论】:

            【解决方案6】:

            函数式编程肯定是另一种范式。也许最简单的理解它的方法是坚持使用流程图来布置设计。每个函数都是不同的,没有继承,没有多态,不同。数据在函数之间传递,以进行删除、更新、插入和创建新数据。

            【讨论】:

            • 我相信一位教授曾经谈到过这个......关于踩踏所有数据以创造新事物的东西。这是他的意思吗?
            • 我相信是的。函数式编程给开发人员/设计人员带来的一个大问题是数据块的维护和馈送。它是独立的,是功能的一部分。您必须非常仔细地构建它以与想要使用它的所有功能兼容。
            • 我完全不推荐流程图。事实上,函数式编程的重点在于,您可以将函数集合建模为单个函数,执行它们所组成的复合转换。
            • -1 函数式编程充满了多态性,比典型的 OOP/命令式编程要多得多。
            【解决方案7】:

            阅读SICP

            另外,还有一个PDF Version 可用。

            【讨论】:

            【解决方案8】:

            鉴于现代函数式语言(即不是 lisps)默认使用早期绑定的多态函数(有效地),并且面向对象只是安排具有多态函数的一种特殊方式,它并没有太大的不同,如果你知道如何设计正确封装的类。

            Lisp 使用后期绑定来实现类似的效果。老实说,没有太大区别,只是你没有显式声明类型的结构。

            如果您已经使用 C++ 模板函数进行了广泛的编程,那么您可能已经有了一个想法。

            在任何情况下,答案都是小“类”,而不是修改内部状态,您必须返回具有不同状态的新版本。

            【讨论】:

            • 真的,有很多相同的东西。只是思维方式不同而已。我注意到在 C 中,我使用结构的方式与使用类的方式相同,这可能是好是坏(我知道 C,但我不是 C-ace)。类似的事情适用吗?
            • 我不确定如何将多态应用到函数式编程中。
            • 您仍然可以修改结构,这是一个区别,但它是一个类似的设计过程。主要区别在于专注于定义明确、行为良好的接口,允许您使用例如迭代功能明智。这种习惯有助于理顺程序结构并加快开发速度。
            • @dacracot - 阅读en.wikipedia.org/wiki/Type_polymorphism 了解多态性如何应用于函数式编程
            • Dacracot,此定义不区分上下文。这个定义也是适用于OO的多态性定义。仅仅因为你不理解它,它不会使它不正确或误导。
            猜你喜欢
            • 2011-01-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-09-12
            • 1970-01-01
            • 1970-01-01
            • 2011-02-10
            • 2023-04-02
            相关资源
            最近更新 更多