【问题标题】:FP modelling - Mutability issue [closed]FP 建模 - 可变性问题 [关闭]
【发布时间】:2012-09-22 20:59:51
【问题描述】:

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

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

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

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

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

【问题讨论】:

  • 您的问题太模糊,无法给出好的答案。
  • 好的,给我一点时间,让它更具体一点。
  • 这类问题对本站来说不够实际或不够具体,您可能会在programmers SE.获得更好的运气
  • 首先,对于真正习惯这两种方法的人来说,我不认为一个人比另一个人花费的时间特别少。其次,您可以例如使温度成为时间的函数(temperature :: Time -> Double),或者使用我们必须模拟可变性的一些机制,或者具有局部可变性,或者只是简单的可变性(通过IORefs 等) .此外,Haskell 中的建模不一定是一方面是数据,另一方面是函数。您的数据可以嵌入函数! data Foo = Foo { f :: Int -> Int, g :: Double -> Double -> Double, somePair :: (Double, Double) }
  • @Alp Mestanogullari:非常感谢您的回答!我不知道数据可以嵌入函数,这就是我真正追求的!我认为温度是时间的函数,但我将如何处理时间的可变性? (我将再次更改问题和标题,以便仅解决参数可变性的问题。如果我的问题最初过于模糊,我很抱歉,我是堆栈溢出的第一个计时器)。

标签: oop haskell functional-programming modeling mutable


【解决方案1】:

仅仅因为某些东西可以改变并不意味着它不能用不可变的数据建模。

在 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 版本中正在发生的事情。给定的命令式代码可以访问的每个可变对象“实际上”是一个额外的输入和一个额外的输出,秘密地和隐式地传递。如果您认为函数式风格使您的程序过于复杂,因为到处都有数十个额外的输入和输出,请问问自己,当所有数据流仍然存在时,程序是否真的没有那么复杂那里但被遮住了?

但是 this 是更高的抽象(例如 monad,但它们不是唯一的)来救援的地方。最好不要把 monad 想成神奇地给你可变状态。相反,将它们视为封装模式,因此您不必像上面那样手动编写代码。当您使用State monad 获得“有状态编程”时,所有这些通过函数输入和输出的状态线程仍在继续,但它是以严格控制的方式完成的,并且正在发生这种情况的函数被标记单子类型,所以你知道它正在发生。

【讨论】:

  • 感谢您非常有见地的回答! Haskell 处理数据操作的方式实际上看起来不像 OOP 那样复杂,我认为它确实显示了操作的数据,例如与 some_object.calculationA 相比。它们本质上是相同的,但正如您在 OOP 中已经说过的那样,“数据流仍然存在,但被掩盖了”。那么,更高的抽象做了 OOP 方法所做的事情,但您知道对哪些数据操作进行了操作?
  • @heaptobesquare 一个使用诸如 monads 之类的概念是为了帮助您编写可以访问某种环境的计算(这种访问可以是只读的,读/写,或者只写,取决于你使用的monad)。你可以用这些概念做很多其他的事情;对于SO的评论甚至答案太多了。用它们自己的术语来理解诸如 monad 之类的东西要比将它们视为您如何实现其他编程语言的概念要容易得多。
猜你喜欢
  • 2017-06-18
  • 1970-01-01
  • 2012-01-31
  • 1970-01-01
  • 2014-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-11
  • 1970-01-01
相关资源
最近更新 更多