我即将开始一个模拟/建模项目。
假设我有一个A类组件,其特征是一组数据(如温度或压力,PDE和某些边界条件等参数)和B类组件,其特征是不同的一组数据(不同或相同的参数,不同的PDE和边界条件)。我们还假设将要应用于每个组件的函数/方法是相同的(例如Galerkin方法)。
如果我使用FP方法,每个组件将分解为数据部分和将作用于数据的函数,以便获得PDE的解决方案。假设参数是常数,这种方法对我来说似乎更简单。如果参数不是常数怎么办(例如,温度突然增加,因此不能是不可变的)?
解决参数可变性问题的最佳方法是什么?
我来自C ++ / Fortran背景,而且我不是一名专业的程序员,所以在我出错的任何事情上纠正我。
答案 0 :(得分:4)
仅仅因为某些事情可以改变并不意味着它不能用不可变数据建模。
在OOish风格中,假设您有以下内容:
a = some_obj.calculationA(some, arguments);
b = some_obj.calculationB(more, args);
return combine(a, b)
显然calculationA
和calculationB
取决于some_obj
,您甚至可以手动线程some_obj
作为两个计算的输入。你只是不习惯看到那就是你正在做的事情,因为你会想到在一个对象上调用一个方法。
以最明显的方式向Haskell中途翻译,可以为您提供以下内容:
let a = calculationA some_obj some arguments
b = calculationB some_obj more args
in combine a b
将some_obj
作为额外参数手动传递给所有函数真的没那么麻烦,因为这就是你在OO风格中所做的事情。
缺少的重要一点是,OO样式calculationA
和calculationB
可能会更改some_obj
,这可能会在此上下文返回后使用。在功能风格中也很明显:
let (a, next_obj) = calculationA some_obj some arguments
(b, last_obj) = calculationB next_obj more args
in (combine a b, last_obj)
我习惯于思考事物的方式,从理论的角度来看,无论如何,这都是“真的”在OOP版本中发生的事情。给定的命令式代码可访问的每个可变对象都是“真正的”额外输入和额外输出,秘密和隐式地传递。如果您认为功能样式会使您的程序过于复杂,因为整个地方都有许多额外的输入和输出,请问自己,当所有数据流仍然那里时,程序是否真的没那么复杂但是模糊不清?
但这个是更高的抽象(例如monad,但他们不是唯一的)来拯救。最好不要把monad想象成神奇地给你可变的状态。相反,将它们视为封装模式,因此您不必手动编写如上所述的代码。当你使用State
monad来获得“有状态编程”时,所有这些通过函数的输入和输出的状态线程仍在继续,但是它是以严格规定的方式完成的,并且在这种情况下运行被monadic类型标记,所以你知道它正在发生。