我正在尝试在Haskell中可视化一些简单的自动物理系统(例如摆锤,机器人手臂等).通常这些系统可以用类似的方程来描述
df/dt = c*f(t) + u(t)
其中,u(t)代表了某种"智能控制"的.这些系统看起来非常适合功能反应式编程范例.
因此,我通过保罗·哈达克抓起书"表达的哈斯克尔学校",并发现,领域特定语言"FAL"(功能动画语言)提出有实际工作相当pleasently我简单的玩具系统(虽然某些功能,尤其是integrate,似乎有点懒得有效使用,但很容易修复).
我的问题是,对于今天更先进甚至实际的应用,更成熟,最新,维护良好,性能优化的替代方案是什么?
这个wiki页面列出了Haskell的几个选项,但我不清楚以下几个方面:
"反应"的状态,来自Conal Eliott的项目(据我所知)是这种编程范式的发明者之一,看起来有点陈旧.我喜欢他的代码,但也许我应该尝试其他更新的替代品?在语法/性能/运行时稳定性方面,它们之间的主要区别是什么?
引用2011年的一项调查,第6节," ...... FRP实施仍然没有足够的效率或足够可预测的性能,无法在需要延迟保证的领域中有效使用...... ".Alghough调查提出了一些有趣的可能的优化,鉴于FRP是有超过15年,我得到的印象是,这个性能问题可能会是一件非常,甚至本来就很难在几年内至少解决.这是真的?
该调查的同一位作者在他的博客中谈到了"时间泄漏" .问题是FRP独有的,还是我们在用纯粹的非严格语言编程时通常会遇到的问题?您是否曾经发现,如果性能不够,那么随着时间的推移稳定基于FRP的系统就太难了?
这还是一个研究水平的项目吗?人们喜欢工厂工程师,机器人工程师,金融工程师等实际使用它们(用适合他们需要的各种语言)吗?
虽然我个人更喜欢Haskell实现,但我愿意接受其他建议.例如,拥有一个Erlang实现会特别有趣 - 那么拥有一个智能的,自适应的,自学的服务器进程就很容易了!
根据这篇文章,
就GHC而言,枚举不算作单构造函数类型,因此当用作严格的构造函数字段或严格的函数参数时,它们不会受益于解包.这是GHC的一个缺陷,但它可以解决.
而是建议使用newtypes.但是,我无法使用以下代码验证这一点:
{-# LANGUAGE MagicHash,BangPatterns #-}
{-# OPTIONS_GHC -O2 -funbox-strict-fields -rtsopts -fllvm -optlc --x86-asm-syntax=intel #-}
module Main(main,f,g)
where
import GHC.Base
import Criterion.Main
data D = A | B | C
newtype E = E Int deriving(Eq)
f :: D -> Int#
f z | z `seq` False = 3422#
f z = case z of
A -> 1234#
B -> 5678#
C -> 9012#
g :: E -> Int#
g z | z `seq` False = 7432# …Run Code Online (Sandbox Code Playgroud) 不像其他不安全*操作,文档的unsafeInterleaveIO是不是其可能存在的缺陷非常明显的.那么到底什么时候不安全?我想知道并行/并发和单线程使用的条件.
更具体地说,以下代码中的两个函数在语义上是等价的吗?如果没有,何时以及如何?
joinIO :: IO a -> (a -> IO b) -> IO b
joinIO a f = do !x <- a
!x' <- f x
return x'
joinIO':: IO a -> (a -> IO b) -> IO b
joinIO' a f = do !x <- unsafeInterleaveIO a
!x' <- unsafeInterleaveIO $ f x
return x'
Run Code Online (Sandbox Code Playgroud)
以下是我在实践中如何使用它:
data LIO a = LIO {runLIO :: IO a}
instance Functor LIO where
fmap f (LIO a) = LIO …Run Code Online (Sandbox Code Playgroud) 在对上一个问题的评论中,我声称:
我有另一个基准来表明ghc-7.4.1 + llvm在严格的数据字段上解压缩枚举.
事实上,经过一些实验,我相信,至少在一些简单的情况下,使用枚举至少与使用新类型的Word8一样快,并且实际上可能更高效(因此在更真实的应用程序中更快) (或Int),即使在数据类型的严格字段中使用.正如我在上一个问题中所说,我在更现实(但仍然很小)的环境中经历了类似的现象.
任何人都能指出一些关于ghc/llvm对枚举的优化的相关参考吗?特别是,它是否真的解压缩严格数据字段上的枚举的内部标记?程序集输出和分析结果似乎表明情况就是这样,但对我来说,核心级别没有任何迹象.任何见解将不胜感激.
还有一个问题:枚举总是至少与相应积分的新类型一样有效,使用它们是否有意义?(请注意,枚举也可以像Integrals一样.)如果不是,那么(希望是否真实有用)异常是什么?Daniel Fischer在他的回答中建议将枚举放在多构造函数数据类型的严格字段上可能会阻止某些优化.但是,我无法在双构造函数的情况下验证这一点.将它们放在大型多构造函数数据类型中时可能有区别吗?
我也很好奇以下基准测试中究竟发生了什么.在所有这四种情况下,堆中分配的字节数大致相同.但是,对于枚举,GC实际上执行的复制较少,并且与newtypes相比,最大驻留时间较小.
(实际上我真正的问题是,当性能很重要时尝试将枚举转换为newtypes是否值得?,但我认为更具体一些可能会更有帮助.)
这个问题的一个可能含义是:如果你在你的程序中使用了大量的Int,它实际上在一个非常小的子集上有所不同,那么将它们更改为枚举(而不是一个未装箱的类型!)可能是一个性能获得(但要严格谨慎).
以下是基准测试的摘要,其后是基准代码和用于在系统上进行测试的便捷makefile.
benchmarking d mean: 11.09113 ns, lb 11.06140 ns, ub 11.17545 ns, ci 0.950 std dev: 234.6722 ps, lb 72.31532 ps, ub 490.1156 ps, ci 0.950 benchmarking e mean: 11.54242 ns, lb 11.51789 ns, ub 11.59720 ns, ci 0.950 std dev: 178.8556 ps, lb 73.05290 ps, ub 309.0252 ps, ci 0.950 benchmarking s mean: 11.74964 ns, lb 11.52543 ns, ub …
想象一下如下的Makefile:
stage1 : Stage1.hs
ghc -o stage1 Stage1.hs
Stage1.hs : stage0
stage0 > Stage1.hs
stage0 : Stage0.hs
ghc -o stage0 Stage0.hs
Run Code Online (Sandbox Code Playgroud)
当前目录首先包含Makefile和Stage0.hs,并生成stage1.
以下是问题:
假设我们想要编写一个由IO操作支持的通用属性映射,但由于某种原因,我们需要使值类型具有多态性.
type Key = Int
get:: Key -> v -> IO v -- Takes a key and a default value, return the associated value
put:: Key -> v -> IO () -- store (Key,v) pair doing some IO
Run Code Online (Sandbox Code Playgroud)
在这种情况下,自由定理是否需要get并且put只做微不足道的事情,如果是这样,我们可以欺骗ghc的类型系统来实现真正的类型索引IO数据库吗?