gpt4 book ai didi

haskell - Haskell 中的程序设计 : how to do simulation without mutability

转载 作者:行者123 更新时间:2023-12-03 11:06:49 25 4
gpt4 key购买 nike

我有一个关于设计我在 Haskell 中工作的程序的最佳方法的问题。我正在编写一个物理模拟器,这是我在标准命令式语言中做了很多事情,通常主要方法看起来像:

while True:
simulationState = stepForward(simulationState)
render(simulationState)

我想知道如何在 Haskell 中做类似的事情。我有一个函数 step :: SimState -> SimState和一个函数 display :: SimState -> IO ()它使用 HOpenGL 来绘制模拟状态,但我不知道如何在某种“循环”中做到这一点,因为我能想出的所有解决方案都涉及某种可变性。当谈到 Haskell 时,我有点菜鸟,所以我完全有可能错过了一个非常明显的设计决定。此外,如果有更好的方法来构建我的整个程序,我会很高兴听到它。

提前致谢!

最佳答案

在我看来,思考这个问题的正确方法不是作为一个循环,而是作为一个列表或其他类似的无限流式结构。我给了a similar answera similar question ;基本思想是,如 C. A. McCann wrote , 使用 iterate stepForward initialState , 其中 iterate :: (a -> a) -> a -> [a] “返回 [ stepForward 的重复应用的无限列表] 到 [ initialState ]”。

这种方法的问题是您无法处理单子(monad)步骤,特别是单子(monad)渲染函数。一种方法是提前获取所需的列表 block (可能使用类似 takeWhile 的函数,可能使用手动递归),然后使用 mapM_ render在那。更好的方法是使用不同的、本质上单子(monad)的流式结构。我能想到的四个是:

  • The iteratee package ,它最初是为流式 IO 设计的。我认为在这里,您的步骤将是一个源( enumerator ),而您的渲染将是一个接收器( iteratee );然后,您可以使用管道( enumeratee )在中间应用功能和/或进行过滤。
  • The enumerator package ,基于相同的想法;一个可能比另一个更干净。
  • The newer pipes package ,它自称是“迭代器做得对”——它更新了,但语义至少对我来说明显更清晰,名称也是如此( ProducerConsumerPipe )。
  • The List package ,尤其是它的ListT单子(monad)变压器。这个 monad 转换器旨在允许您创建比 [m a] 更有用的结构的 monadic 值列表。 ;例如,使用无限单子(monad)列表变得更易于管理。该软件包还将列表上的许多功能概括为 a new type class .它提供了一个 iterateM功能两次; first time令人难以置信的普遍性,而 second time专门为ListT .然后,您可以使用 takeWhileM 等函数。做你的过滤。

  • 在某些数据结构中具体化程序的迭代而不是简单地使用递归的一大优势是,您的程序可以使用控制流做有用的事情。当然,没有什么过于浮夸,但例如,它将“如何终止”决策与“如何生成”过程分开。现在,用户(即使只是你)可以单独决定何时停止:在 n 步之后?在状态满足某个谓词之后?没有理由因为这些决定而使您的生成代码陷入困境,因为它在逻辑上是一个单独的问题。

    关于haskell - Haskell 中的程序设计 : how to do simulation without mutability,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9548913/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com