我正在考虑将C#应用程序转换为Haskell,作为我的第一个“真正的”Haskell项目。然而,我想确保这是一个有意义的项目。该应用程序收集来自大约1 kHz的15条串行流的数据包,将这些值加载到我的“上下文”对象上相应的循环缓冲区中,每个缓冲区都有25000个元素,然后在60 Hz时将这些数组发送到OpenGL进行波形显示。(因此,它必须作为数组存储,或者至少每16 ms转换成一个数组)。我的上下文对象上还有大约70个字段,我只维护当前(最新)值,而不是流波形。
这个项目有几个方面可以很好地映射到Haskell,但我担心的是性能。如果对于任何流中的每一个新的数据池,我必须用70个字段和15个25000元素数组克隆整个上下文对象,那么显然会出现性能问题。
我能把所有的东西都放在IO-monad里来解决这个问题吗?但这似乎有点辜负了使用Haskell的目的,对吗?另外,我在C#中的所有代码都是事件驱动的;在Haskell中有这样的成语吗?似乎添加一个侦听器会产生一个“副作用”,我不知道具体是如何做到的。
发布于 2012-01-31 11:39:26
是的,您可能希望对可变数据使用IO monad。我不认为ST monad适合这个问题空间,因为数据更新与实际的IO操作(读取输入流)交织在一起。由于您需要使用unsafeIOToST在ST中执行IO,所以我发现最好直接使用IO。使用ST的另一种方法是不断地解冻和冻结数组;这很麻烦,因为您需要保证数据的旧副本永远不会被使用。
尽管证据显示认为纯解决方案(以Data.Sequence.Seq的形式)通常比使用可变数据更快,但考虑到将数据推送到OpenGL的要求,直接使用数组可以获得更好的性能。我将使用来自Data.Vector.Storable.Mutable的函数(来自向量包),因为您可以访问ForeignPtr进行导出。
您可以查看箭头(雅帕)中一种非常常见的事件驱动代码方法。另一个领域是功能反应性(FRP)。在这个领域开始有一些相当成熟的库,如Netwire或反应性香蕉。不过,我不知道它们是否为您的需求提供了足够的性能;我主要是在gui类型的编程中使用它们。
发布于 2012-01-31 01:08:45
请看这个链接,在“ST monad”一节中:
http://book.realworldhaskell.org/read/advanced-library-design-building-a-bloom-filter.html
在名为“修改数组元素”的部分中,我们提到修改不可变数组是非常昂贵的,因为它需要复制整个数组。使用UArray不会改变这一点,那么我们能做些什么来将成本降低到可以承受的水平呢? 在命令式语言中,我们将简单地修改数组的元素;这也是我们在Haskell中的方法。 Haskell提供了一个特殊的monad,名为ST,它允许我们在可变状态下安全工作。与国家单曲相比,它有一些强大的附加能力。 我们可以解冻不可变数组以提供可变数组;修改可变数组;完成操作后冻结一个新的不可变数组。
..。
IO monad也提供了这些功能。两者的主要区别在于,ST monad是有意设计的,这样我们就可以从它逃回纯粹的Haskell代码。
因此,应该可以就地修改,而且它终究不会辜负使用Haskell的目的。
https://stackoverflow.com/questions/9072964
复制相似问题