FP用于仿真和建模


12

我将要开始一个模拟/建模项目。我已经知道OOP用于此类项目。但是,研究Haskell使我考虑使用FP范例对组件系统进行建模。让我详细说明:

假设我有一个类型A的组件,其特征是一组数据(如温度或压力,PDE和某些边界条件等参数),以及一个类型B的组件,其特征是一组不同的数据(不同或相同的参数,不同的PDE和边界条件)。我们还假设将要应用于每个组件的函数/方法是相同的(例如,Galerkin方法)。对象的可变状态将用于非恒定参数。

如果要使用OOP方法,我将创建两个对象,这些对象将封装每种类型的数据,解决PDE的方法(继承将在此处用于代码重用)和PDE的解决方案。

另一方面,如果我要使用FP方法,则每个组件都将分解为数据部分和对数据起作用的功能,以获得PDE的解决方案。非常数参数将作为其他函数(例如时间)传递或由某种可变性(可变性的仿真等)表示。假设对数据进行线性运算是微不足道的,这种方法对我来说似乎更简单。

总之,与OOP相比,实施FP方法实际上是否更简单,更易于管理(添加不同类型的组件或新方法来解决pde)?

我来自C ++ / Fortran,而且我不是专业程序员,所以请在出现任何错误的地方进行纠正。

Answers:


7

好问题,我一直在考虑类似的思路。从历史上看,OO范式源于对计算机仿真的需求-请参见Simula的历史-尽管早期的OO语言(例如Smalltalk)是由知道自己在做什么的人(例如Alan Kay)制作的,但现在可以说OO被过度使用并且带来太多的意外复杂性

通常,与OO程序相比,FP风格的程序更短,更易于测试且更易于修改。正如罗布·哈罗普(Rob Harrop)在演讲中所说,“未来是否有用?” ,您永远无法比功能和数据更简单;两者组成无限,以建立所需的任何抽象。因此,回答您问题的一种方法(或者我只是重申一下?:)是问,什么是最高级别的函数,以及最高级别的输入数据->输出数据是什么样的?然后,您可以将这些“ alpha”函数和数据类型分解为下一层抽象,并根据需要重复。

关于您的问题的另一种观点(不是很完全的答案)是在StackOverflow上查看此线程(免责声明,我已经开始了),其中一些答案非常有趣:https : //stackoverflow.com/questions/3431654/how-does-功能编程应用于模拟

在这一点上,我个人的观点是,除非您要建模的情况是确实存在离散对象,它们仅以确定的方式相互作用(例如,计算机网络的模型),从而直接映射到干净的消息功能,传递范式OO语言-使用FP更简单。请注意,即使在游戏编程社区(模拟非常普遍且性能要求至关重要)中,经验丰富的开发人员也正在远离OO范式和/或使用更多FP,例如,请参阅本HN讨论John Carmack关于FP的评论


很高兴知道我不是唯一一个对模拟中的OOP表示怀疑的人,并感谢您回答我的问题!我已经阅读了John Carmack关于FP的评论,并考虑过在C ++上实现FP的某些方面(复制对象,或收集输入并将其传递给函数),但是我又不知道是否应该使用C ++启动项目而不是像Haskell这样的FP语言,因为FP方面是内置的,并且仅在需要时才表达可变性。考虑到您遇到类似的问题/问题,您是否总体上继续使用Clojure或FP?
heaptobesquare

@heaptobesquare-是的,我一直在稳步提高我的Clojure-fu的目标是在其中编写模拟。尚无要显示的内容,但我看不到任何显示阻止者,Clojure的设计非常实用,例如,您可以根据需要使用瞬态/变异,而且其代理非常适合异步方面。在某个时候(什么时候没有保证),我将写一篇有关该主题的文章...
limist

我看过Clojure,但不能说我喜欢S表达式。我知道它是实用的(Lisp代码是数据),但是容易适应吗?
heaptobesquare

@heaptobesquare-s-expressions / Lisp语法实际上非常容易习惯;首先选择一个具有Clojure模式的优秀编辑器(Emacs或vim,我的投票是对Emacs的支持,请参见dev.clojure.org/display/doc/Getting+Started+with+Emacs),获得一本好书(例如Programming Clojure) ),然后开始黑客入侵。最多过几周后,语法便会淡入背景,因为它是如此的完美一致,以至于您会以更少的频率指数地想到它,并释放了更多重要事情的思维周期。:)
limist 2012年

那我一定会试试看。毕竟Lisp的谐音很有趣。
heaptobesquare

2

恕我直言,对于几乎每一个合理复杂性的任务,都无法客观地回答“ FP风格还是OOP风格是更好的选择”的问题。通常,在这种情况下,问题不是“ FP还是OOP”,而是如何结合两个范例的最佳部分来解决您的问题。

您上面提到的问题似乎是一个非常数学的问题,我大胆猜测您将需要一些矩阵运算。OOP非常适合对抽象数据类型进行建模,并且矩阵演算可以通过对矩阵的操作轻松地实现为“矩阵对象”。以所有矩阵运算都属于矩阵类的一部分的方式来实现此方法,可以帮助您将属于一起的事物保持在一起,从而保持良好的整体结构。

另一方面,PDE是关于函数的方程,解可能又是函数。因此,对于这种类型的“组件”使用功能性方法似乎很自然。这些函数可能具有矩阵参数,显示了如何组合OOP和FP的一个示例。另一个示例是矩阵类实现,该实现使用功能性工具将特定操作映射到矩阵的每个元素。因此,在这里也不是“ OOP vs FP”而是“ OOP与FP结合”为您带来最佳效果。


谢谢您的回答!因此,如果我在哪里使用C ++,将仅将组件的数据(即参数,边界条件和矩阵形式的PDE)封装到对象中,并定义函数(甚至某些高阶函数)。参数是其他函数的函数),在对象范围之外,可以对对象数据进行操作,是否有效?
heaptobesquare

@heaptobesquare:老实说,我不能告诉您这是否对有效。尝试一下,从大处着手,从小处开始。开始编写一些“跟踪代码”(artima.com/intv/tracer.html),以找出最有效的方法和无效的方法。而且,如果您发现某些地方无法正常工作,请进行重构。
布朗

Haskell具有Hmatrix库,该库是BLAS / LAPACK库的绑定,并且具有非常好的语法,我可以亲自选择OOP方法。
2012年

@paul:谢谢,我一定会看一下!Haskell库是否普遍一致且内容丰富?维基这么说,但这是事实吗?
heaptobesquare

@heaptobesquare:我在任何程度上都使用过的唯一Haskell库是Parsec(我用它来编写汇编器),但是我喜欢使用它。我只对Hmatrix和Haskell OpenGL绑定进行了GHCI探索,但它们看起来相当不错。Hmatrix看起来几乎和MATLAB一样简洁(我已经使用了很多),它是专门为这种事情而制作的。根据我有限的经验,库是一致的-这是因为Haskell是基于少量的简单构建基块构建的-它们也很丰富,因为Haskellers不喜欢做世俗的事情:)
paul,
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.