haskellyampa

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


I'm trying to get to grips with Yampa, but from the definition of the higher-level signal functions like integral it's not obvious to me how I would define such signal functions myself with Yampa's exported combinators with idiomatic Haskell (I don't care about performance at the moment). My goal is to learn how I can write my own combinators for debouncing, buffering, grouping, etc.

The integral function is defined with the unexported constructors SF and SF'. How can I write it only with the other exported combinators, possibly using a more idiomatic Yampa style with switches and arrow notation?

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

Solution

  • The unexported constructors can be changed for exported versions by looking at identity, constant, arrPrim, etc., but I found it more interesting to take the more general approach of using causal commutative arrows from the research of Hai Liu et al.

    An accompanying repository shows an integral implementation in the style I want:

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

    For understanding it, reading Hai's papers has helped me, as they go into several examples. If we assume x to be a stream of Doubles, then the stream i' of integral values after reading the respective samples equals the stream of integral values before reading the respective samples plus the following input element multiplied by the time step (which is fixed in this formulation), and the stream of integral values i is calculated for the first sample as 0 (init 0) and for following samples from i'. In Yampa, init is called iPre.