Questions tagged «functional-programming»

函数式编程是一种范式,它试图通过对函数的链式评估来解决计算问题,这些函数的输出由输入决定,而不是由程序状态决定。在这种编程方式中,不赞成使用副作用和可变数据,并且通常严格隔离它们。


2
函数式程序员使用什么代替UML?
我是CS学生。我目前正在参加讲座,在那里我们将学习目标分析和设计。它主要由编写用例,分析我们为客户编写一些应用程序时可能遇到的问题以及如何设计项目以使其既可扩展,对开发人员清晰又不会在客户争论某些问题时产生问题而组成特征。由于它是“客观的”,因此我们是从OOP(类等)的角度来学习它的。 现在,我们使用UML作为帮助工具。我相信我对OOP有很好的了解,但是我也学习了功能范例,并在我的一些较小的项目中成功使用了它。 我们的老师面对“功能范式有什么意义”?问题,他回答他没有使用功能语言编写任何更大的项目,并且他不知道功能程序可以使用哪种工具。 那么,他们将使用什么呢?有一些方法吗?或者也许不需要这种东西?

4
模式匹配是惯用的类型还是不良的设计?
似乎F#代码经常针对类型进行模式匹配。当然 match opt with | Some val -> Something(val) | None -> Different() 似乎很常见。 但是从OOP的角度来看,这看起来非常像基于运行时类型检查的控制流,通常会对此皱眉。要说明,在OOP中,您可能更喜欢使用重载: type T = abstract member Route : unit -> unit type Foo() = interface T with member this.Route() = printfn "Go left" type Bar() = interface T with member this.Route() = printfn "Go right" 这肯定是更多代码。OTOH,在我的OOP-y看来,它具有结构上的优势: …

1
发生器功能在功能编程中有效吗?
问题是: 生成器是否破坏了功能编程范式?为什么或者为什么不? 如果可以,可以在函数式编程中使用生成器吗?如何使用? 考虑以下: function * downCounter(maxValue) { yield maxValue; yield * downCounter(maxValue > 0 ? maxValue - 1 : 0); } let counter = downCounter(26); counter.next().value; // 26 counter.next().value; // 25 // ...etc 该downCounter方法显示为无状态。同样,downCounter使用相同的输入进行调用将始终导致相同的输出。但是,同时,调用next()不会产生一致的结果。 我不确定生成器是否会破坏函数式编程范式,因为在此示例中counter是生成器对象,因此调用next()将产生与使用完全相同的另一个生成器对象产生的结果相同的结果maxValue。 同样,调用someCollection[3]数组将始终返回第四个元素。同样,next()在生成器对象上调用四次也会始终返回第四个元素。 为了获得更多的上下文,在编写kata编程时提出了这些问题。回答问题的人提出了一个问题,即生成器是否可以在函数式编程中使用以及它们是否保持状态。

5
如果将函数作为参数,函数是否立即不纯?
由于输入参数的纯度直到运行时才是未知的,如果将函数作为输入参数,该函数是否立即被认为是不纯的? 相关:如果一个函数应用了一个在函数外部定义的纯函数,但没有作为参数传递,那么它是否满足纯函数的要求,即输出是否仅取决于输入,它是否仍然是纯函数? 对于上下文,我正在用JavaScript编写功能代码。

4
IO monad模式处理副作用的好处是否纯粹是学术上的?
对不起,还有另一个FP +副作用问题,但是我找不到一个可以完全回答我的问题。 我对函数式编程的(有限的)理解是,应将状态/副作用最小化并与无状态逻辑分开。 我还收集了Haskell的方法,即IO monad,它通过将有状态的动作包装在一个容器中以供以后执行(被认为超出程序本身的范围)来实现。 我试图理解这种模式,但实际上是确定是否在Python项目中使用它,因此要避免使用Haskell规范。 粗暴的例子来了。 如果我的程序将XML文件转换为JSON文件: def main(): xml_data = read_file('input.xml') # impure json_data = convert(xml_data) # pure write_file('output.json', json_data) # impure IO monad的方法不是有效地做到这一点: steps = list( read_file, convert, write_file, ) 然后通过不实际调用这些步骤来放任自己的责任,而是让口译员这样做? 换一种说法,就像写: def main(): # pure def inner(): # impure xml_data = read_file('input.xml') json_data = convert(xml_data) write_file('output.json', …

5
是什么使函数式编程语言声明式而不是命令式?
在许多描述函数式编程优势的文章中,我看到函数式编程语言(例如Haskell,ML,Scala或Clojure)被称为“声明性语言”,与命令式语言(例如C / C ++ / C#/ Java)不同。我的问题是什么使函数式编程语言具有声明性而非命令性。 一个经常遇到的描述声明式和命令式编程之间差异的解释是,在命令式编程中,您告诉计算机“如何做某事”,而不是声明性语言中的“做什么”。我在此说明中遇到的问题是,您在所有编程语言中都经常这样做。即使您进入最低级别的程序集,您仍在告诉计算机“该怎么做”,您告诉CPU将两个数字相加,但并没有指示它如何执行加法。如果我们走到另一端,像Haskell这样的高级纯函数式语言,实际上就是在告诉计算机如何完成特定任务,这就是您的程序所要执行的一系列指令,计算机无法单独实现这些任务。我了解到,Haskell,Clojure等语言显然比C / C ++ / C#/ Java高,并提供诸如惰性求值,不可变数据结构,匿名函数,currying,持久数据结构等功能,所有这些使得函数式编程是可能且高效的,但我不会将它们归类为声明性语言。 对我而言,纯声明性语言将是仅由声明完全构成的语言,此类语言的示例将是CSS(是的,我知道CSS从技术上讲不是编程语言)。CSS只包含页面的HTML和Javascript使用的样式声明。CSS除了作声明外,不能做任何其他事情,它不能创建类函数,即,基于某些参数确定要显示的样式的函数,您无法执行CSS脚本等。对于我来说,它描述了声明性语言(注意,我没有说声明性语言编程语言)。 更新: 我最近一直在使用Prolog,对我而言,Prolog是最接近完全声明式语言的编程语言(至少在我看来),如果它不是唯一的完全声明式编程语言。要详细说明Prolog中的编程,请进行声明,声明要说明事实(规则(对于特定输入返回true的谓词函数))或规则(对基于输入的给定条件/模式返回true的谓词函数),规则使用模式匹配技术定义。要在序言中做任何事情,您都可以通过用变量替换谓词的一个或多个输入来查询知识库,而序言会尝试查找谓词成功的变量的值。 我的观点是在序言中没有强制性指令,您基本上是在告诉(声明)计算机知道的信息,然后询问(查询)有关知识的信息。在函数式编程语言中,即使您不是直接操作内存位置或不逐步编写计算,也仍在给出指令,即获取值,调用函数X并为其添加1等。从这个意义上讲,我不会说用Haskell,ML,Scala或Clojure进行编程是声明性的,尽管我可能是错的。在我上面所描述的意义上,它是正确,真实,纯函数式的声明式编程。

4
函数式编程会增加代码的复杂性吗?[关闭]
已关闭。这个问题是基于观点的。它当前不接受答案。 想改善这个问题吗?更新问题,以便通过编辑此帖子以事实和引用的形式回答。 5年前关闭。 在过去的一年中,我一直在编写Scala代码(来自Java背景)。我真的很喜欢如何使用val,case类,map / filter / lambda函数,隐式函数和类型推断来创建更简单,更简洁的代码。我主要将其用于基于Akka的应用程序。 今年,我和一个新团队一起在Scala项目中,他们非常喜欢函数式编程。他们大量使用Scalaz,并且代码到处都是应用程序,上下文边界,读取器/写入器/状态monad,甚至是将主要方法“包装”在I / O monad中。他们的理由是,这使编译器在断言代码正确且每个函数都没有副作用的情况下“为我们工作”。 即便如此,从我的角度来看,所有这些语法确实确实妨碍了业务逻辑。例如,可以使用“ MyBusinessObject”类型,也可以使用“ List [MyBusinessObject]”,“ Option [MyBusinessObject]”或“ Future [MyBusinessObject]”类型。它们都有明确的含义和目的。另一方面,代码如下: def method[M[_]: Applicative] = { case (a, b) => (ca[M](a) |@| cb[M](b)) { case t @ (ra, rb) => if (ra.result && rb.result) t.right else t.left } } 它会增加程序的复杂性吗?还是我不习惯这种编程方式?

4
非功能语言中持久数据结构的使用
纯粹的功能或近乎纯功能的语言会从持久性数据结构中受益,因为它们是不可变的,并且非常适合无状态编程功能。 但是,我们不时看到用于Java等(基于状态的OOP)语言的持久数据结构库。人们经常听到有人主张使用持久性数据结构,因为它们是不可变的,因此是线程安全的。 但是,持久性数据结构是线程安全的,原因是,如果一个线程将一个元素“添加”到持久性集合中,则该操作将返回一个新集合,就像原始集合一样,但是添加了元素。因此,其他线程将看到原始集合。当然,这两个集合共享许多内部状态-这就是为什么这些持久性结构有效的原因。 但是,由于不同的线程看到的数据不同的状态,它似乎是持久数据结构是不是本身足以处理的情况,其中一个线程进行更改,对于其它线程是可见的。为此,似乎我们必须使用诸如原子,引用,软件事务性存储器乃至经典锁和同步机制之类的设备。 那么为什么PDS的不变性被吹捧为有利于“线程安全”的东西呢?在PDS协助同步或解决并发问题方面,有没有真实的例子?还是PDS只是一种为对象提供无状态接口以支持功能编程风格的方式?

7
有关函数式编程的无障碍书籍[关闭]
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案会得到事实,参考或专业知识的支持,但是这个问题可能会引起辩论,争论,民意调查或扩展讨论。如果您认为此问题可以解决并且可以重新提出,请访问帮助中心以获取指导。 8年前关闭。 我正在寻找一本以易用的方式介绍函数式编程的书。另外,我更喜欢一种不太沉闷并且不使用深奥语言的语言。 理想情况下,它将使用示例来演示函数式编程比命令式方法导致更优雅或更简单的解决方案的情况。 我有相当数量的编程经验,但没有函数式编程知识。谢谢你的建议

3
Ur / Web用于网络编程的新的纯功能语言?[关闭]
已关闭。这个问题是基于观点的。它当前不接受答案。 想改善这个问题吗?更新问题,以便通过编辑此帖子以事实和引用的形式回答。 4年前关闭。 在搜索类似Haskell的语言的Web框架时遇到了Ur / Web项目。它看起来像一个人完成的非常有趣的项目。 基本上,它是Web编程的领域特定的纯功能语言,它充分利用了ML和Haskell的优势。语法是ML,但是Haskell有类型类和monad,并且经过严格评估。服务器端被编译为本地代码,客户端被编译为Javascript。有关其他广告优势,请参见幻灯片和常见问题页面。 查看这些演示及其源代码,我认为该项目非常有前途。最新版本是20110123,因此目前似乎正在积极开发中。 这里有人有进一步的经验吗?与ML稍微冗长的语法相比,与Haskell相比是否存在问题/烦恼?

2
什么是Comonad,它们有什么用?
最近,我一直在整理关于Monads工作原理的知识。还向我介绍了'Comonad'的概念,它被描述为monad 的逆对偶。但是,我不可能把头缠住它。 为了了解Monad,我为自己做了一个比喻: Monads可以看作是“构建表达传送带的蓝图”。 要定义一个新的Monad(一种新型的传送带系统),您需要定义: 一种在传送带上放置东西的方法,例如“启动”传送带。(称为unit或return) 将作为传送带一部分的机器(表达式)连接到传送带的一种方式。(称为join或bind或>>=)。 (第三项操作是将当前的传送带取走,将其内含物扔掉,然后启动一个新的传送带,称为>>,但很少使用。) 为了使机器和输送机正常工作,您需要确保: 如果将某些东西放在传送带上并使其通过机器,则输出应与手动将其通过机器时的输出相同。(左身份) 如果要将传送带放在已经存在的传送带之间,则不应以顶部带有传送带的传送带结尾,而应使用一条更长的传送带。 (正确身份) 如果您手动使用机器A,然后将结果传递到连接传送带的BC,或者如果您使用机器,将结果传递给连接的AB,然后手动将结果传递给C,则对于输出无所谓。 >> = b)>> = c)应该与(a >> =(b >> = c))相同(关联性) 最简单的传送带就是那种只接受输入并始终继续到下一个表达式的传送带。这就是“管道”。 另一种可能性是,只有在满足该条件的条件下,才让它通过下一台机器。这意味着,如果在它们之间的某些表达式中,该值更改为不再允许的值,则将跳过其余的表达式。这就是“也许”单子在Haskell中所做的事情。 您还可以在将值传递到计算机之前或之后对值执行其他特殊的条件性复制/更改规则。一个示例:解析器(此处,如果表达式返回“失败”结果,则将表达式之前的值 用作输出)。 当然,这个比喻不是完美的,但我希望它能很好地说明单子的工作原理。 但是,我很难理解这种类比,以理解Comonads。我从互联网上发现的少量信息中得知Comonad定义了以下信息: extract,这与的相反return,也就是说,它从 Comonad中取出一个值。 duplicate,这与的倒数相同join,也就是说,它从一个中创建了两个Comonad。 但是,如果我们只能从它们中提取或复制它们,该如何实例化Comonad?以及如何实际使用它们?我已经看到了这个非常了不起的项目以及有关它的讨论(很遗憾,我对此了解很少),但是我不确定Comonad到底提供了部分功能。 什么是Comonad?它们有什么用?如何使用它们?它们可食用吗?

6
一种基于限制传递给函数的参数数量的语言
这个想法的灵感来自事实运算符,例如+,-,%等,可以看作是传递了一个或两个参数且没有副作用的函数。假设我或其他人编写了一种语言,该语言可以阻止传递两个以上的参数,并且也只能通过返回值来工作: a)这样的语言会导致更容易理解的代码吗? b)代码流程会更清晰吗?(被强制执行更多的步骤,可能会减少“隐藏”的互动 c)限制是否会使该语言在更复杂的程序中显得过于庞大。 d)(奖励)对优点/缺点的任何其他评论 注意: 仍然必须做出两个决定-第一个是是否允许用户在main()或其等效外部进行输入,以及关于传递数组/结构时将发生什么的规则。例如,如果某人希望单个函数添加多个值,则可以通过将其捆绑到数组中来解决该限制。可以通过不允许数组或结构与其自身进行交互来阻止这种情况,例如,仍然可以使您根据位置将每个数字除以不同的数量。

5
接口(OOP)的语义约定是否比功能签名(FP)更具信息意义?
有人说,如果您将SOLID原理付诸实践,那么您最终会从事函数式编程。我同意本文的观点,但是我认为从接口/对象到函数/闭包的转换会丢失一些语义,并且我想知道函数式编程如何减轻这种损失。 从文章: 此外,如果您严格地应用接口隔离原理(ISP),您将了解您应该比角色头接口更喜欢角色接口。 如果您继续将设计推向越来越小的界面,那么最终您将获得最终的角色界面:使用单一方法的界面。这在我身上经常发生。这是一个例子: public interface IMessageQuery { string Read(int id); } 如果我依赖IMessageQuery,则隐式合同的一部分是调用Read(id)将搜索并返回具有给定ID的消息。 将此与对其等效功能签名的依赖进行比较 int -> string。没有任何其他提示,此功能可能很简单ToString()。如果您使用A实施IMessageQuery.Read(int id),ToString()我可能会指责您故意颠覆性! 那么,函数式程序员可以做什么来保留命名接口的语义?例如,创建具有单个成员的记录类型是常规做法吗? type MessageQuery = { Read: int -> string }

2
高阶参数多态性有用吗?
我很确定每个人都熟悉以下形式的通用方法: T DoSomething<T>(T item) 此功能也称为参数多态(PP),特别是等级1 PP。 假设可以使用以下形式的函数对象来表示此方法: <T> : T -> T 即,<T>意味着需要一种类型的参数,以及T -> T装置,它需要类型的一个参数T并返回相同的类型的值。 那么以下将是2级PP函数: (<T> : T -> T) -> int 该函数本身不接受任何类型参数,但接受一个具有类型参数的函数。您可以迭代地继续进行此操作,使嵌套越来越深,PP等级越高。 在编程语言中,此功能确实很少见。默认情况下,甚至Haskell也不允许。 它有用吗?它可以描述很难用其他方式描述的行为吗? 此外,强制性意味着什么?(在这种情况下)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.