根据 Yampa 的 public API 定义信号函数,例如 "integral"

Define signal function like "integral" in terms of Yampa's public API

我正在尝试掌握 Yampa,但是从像 integral 这样的高级信号函数的定义来看,我不清楚如何使用 Yampa 的导出组合器自己定义这样的信号函数使用惯用的 Haskell (我现在不关心性能)。我的目标是学习如何编写自己的组合器来进行去抖动、缓冲、分组等。

integral 函数是使用未导出的构造函数 SFSF' 定义的。我怎样才能只用其他导出的组合器来编写它,可能使用带有开关和箭头符号的更惯用的 Yampa 样式?

integral :: VectorSpace a s => SF a a
integral = SF {sfTF = tf0}
    where
        tf0 a0 = (integralAux igrl0 a0, igrl0)

        igrl0  = zeroVector

        integralAux igrl a_prev = SF' tf -- True
            where
                tf dt a = (integralAux igrl' a, igrl')
                    where
                       igrl' = igrl ^+^ realToFrac dt *^ a_prev

可以通过查看 identityconstantarrPrim 等更改导出版本的未导出构造函数,但我发现采用更通用的方法更有趣使用 Hai Liu 等人研究中的因果交换箭头

accompanying repository 显示了我想要的样式的 integral 实现:

integral :: ArrowInit a => a Double Double
integral = proc x -> do
  rec let i' = i + x * dt
      i <- init 0 -< i'
  returnA -< i

为了理解它,阅读 Hai 的论文对我有帮助,因为它们有几个例子。如果我们假设 x 是一个 Double 流,那么读取各个样本之后的整数值流 i' 等于读取各个样本之前的整数值流加上后面的输入元素乘以时间步长(在此公式中是固定的),并且积分值流 i 对于第一个样本计算为 0 (init 0),对于来自 i' 的后续样本计算。在 Yampa 中,init 被称为 iPre