-- | -- Module: FRP.Netwire.Move -- Copyright: (c) 2013 Ertugrul Soeylemez -- License: BSD3 -- Maintainer: Ertugrul Soeylemez <es@ertes.de> module FRP.Netwire.Move ( -- * Calculus derivative, integral, integralWith ) where import Control.Wire -- | Time derivative of the input signal. -- -- * Depends: now. -- -- * Inhibits: at singularities. derivative :: (RealFloat a, HasTime t s, Monoid e) => Wire s e m a a derivative = mkPure $ \_ x -> (Left mempty, loop' x) where loop' x' = mkPure $ \ds x -> let dt = realToFrac (dtime ds) dx = (x - x') / dt mdx | isNaN dx = Right 0 | isInfinite dx = Left mempty | otherwise = Right dx in mdx `seq` (mdx, loop' x) -- | Integrate the input signal over time. -- -- * Depends: before now. integral :: (Fractional a, HasTime t s) => a -- ^ Integration constant (aka start value). -> Wire s e m a a integral x' = mkPure $ \ds dx -> let dt = realToFrac (dtime ds) in x' `seq` (Right x', integral (x' + dt*dx)) -- | Integrate the left input signal over time, but apply the given -- correction function to it. This can be used to implement collision -- detection/reaction. -- -- The right signal of type @w@ is the /world value/. It is just passed -- to the correction function for reference and is not used otherwise. -- -- The correction function must be idempotent with respect to the world -- value: @f w (f w x) = f w x@. This is necessary and sufficient to -- protect time continuity. -- -- * Depends: before now. integralWith :: (Fractional a, HasTime t s) => (w -> a -> a) -- ^ Correction function. -> a -- ^ Integration constant (aka start value). -> Wire s e m (a, w) a integralWith correct = loop' where loop' x' = mkPure $ \ds (dx, w) -> let dt = realToFrac (dtime ds) x = correct w (x' + dt*dx) in x' `seq` (Right x', loop' x)