0

我即将开始一个模拟/建模项目。

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

如果我使用 FP 方法,每个组件都将被分解为数据部分和作用于数据的函数,以获得 PDE 的解决方案。假设参数是恒定的,这种方法对我来说似乎更简单。如果参数不是恒定的(例如,温度突然升高,因此不可能是不变的)怎么办?

解决参数可变性问题的最佳方法是什么?

我来自 C++/Fortran 背景,而且我不是专业程序员,所以请纠正我的任何错误。

4

1 回答 1

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 想成神奇地给你可变状态。相反,将它们视为封装模式,因此您不必像上面那样手动编写代码。当您使用Statemonad 进行“有状态编程”时,所有这些通过函数的输入和输出的状态线程仍在继续,但它是以严格控制的方式完成的,并且正在发生这种情况的函数由 monadic 标记类型,所以你知道它正在发生。

于 2012-10-02T01:55:07.473 回答