FP建模 - 可变性问题

时间:2012-10-02 00:27:05

标签: oop haskell functional-programming modeling mutable

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

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

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

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

我来自C ++ / Fortran背景,而且我不是一名专业的程序员,所以在我出错的任何事情上纠正我。

1 个答案:

答案 0 :(得分:4)

仅仅因为某些事情可以改变并不意味着它不能用不可变数据建模​​。

在OOish风格中,假设您有以下内容:

a = some_obj.calculationA(some, arguments);
b = some_obj.calculationB(more, args);
return combine(a, b)

显然calculationAcalculationB取决于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样式calculationAcalculationB可能会更改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类型标记,所以你知道它正在发生。