Yes indeed. Many thanks for catching these bugs. Fixed now in the text.

]]>(fs’,fs”) = splitAt fd fs (xs’,xs”) = splitAt xd xs

The fd and the xd are reversed.

]]>-- A time series association list into a signal aList2Sig :: Num a => [(a, b)] -> a :-> b aList2Sig = S . uncurry (zipWith (t a -> FS t (const a))) . first makeSeries . unzip where makeSeries xs = zipWith (-) xs (0:xs) -- A times series association list into a signal, with linear interpolation aList2InterpSig :: Fractional a => [(a, a)] -> a :-> a aList2InterpSig xs = S $ zipWith interp ((0,0):xs) xs interp :: Fractional b => (b,b) -> (b,b) -> b :-># b interp (x,y) (x',y') = FS dx $ x'' -> ((y' - y) / dx) * x'' + y where dx = x' - x -- Takes a bijection (could use TypeCompose for full effect) and alters the signal such that -- its input is now that bijection. This only works on signals and not general segments. -- There should be some way to generalize it with a typeclass, but I'm not sure how. -- Arrows might help? class Bijectable where...? changeInput :: (s -> t) -> (t -> s) -> (s :-> a) -> t :-> a changeInput g g' = inS . map $ (FS t f) -> FS (g t) (f . g') -- Using the bijection machinery, scales a signal over time. -- (scaling over the y axis is just via fmap) scaleBy :: (Fractional s) => s -> (s :-> a) -> s :-> a scaleBy v = changeInput (v*) (/v) -- Transformations between relative and absolute representations -- can be more generalized beyond just days -- perhaps even as some sort of meta-bijection pair? atDay :: (RealFrac b) => Day -> (b :-> a) -> Day :-> a atDay d = changeInput (flip addDays d . round) (fromIntegral . flip diffDays d) relativeFrom :: (RealFrac b) => Day -> (Day :-> a) -> b :-> a relativeFrom d = changeInput (fromIntegral . flip diffDays d) (flip addDays d . round) -- Class of things whose values can be sampled class Sample v t a | v -> t a where sampleAt :: v -> t -> a sampleAts :: v -> [t] -> [a] sampleAts v = map (sampleAt v) instance Sample [a] Int a where sampleAt = atNote "sampleAt" instance (Num t, Ord t) => Sample (t :-> a) t a where sampleAt (S xs) t = mconcat xs `sampleAt` t sampleAts (S xs) ts = mconcat xs `sampleAts` ts -- Use the Chart library (previous version [0.8]) to plot signals over inputs. plotSig :: Sample v Double Double => String -> v -> [Double] -> Double -> Renderable plotSig t v ts maxval = toRenderable $ defaultLayout1 { layout1_title = t, layout1_horizontal_axes = linkedAxes (autoScaledAxis defaultAxis), layout1_vertical_axes = linkedAxes (autoScaledAxis defaultAxis), layout1_plots = [("",HA_Bottom,VA_Left,toPlot myPlot), ("",HA_Bottom,VA_Left,toPlot myFillPlot)] } where myPlot = defaultPlotLines { plot_lines_values = [filter ((Point _ y) -> y <= maxval) $ zipWith Point ts (v `sampleAts` ts)] } myFillPlot = defaultPlotPoints { plot_points_style=filledCircles 2 (Color 1 0 0), plot_points_values=[Point 0 0, Point (maximum ts) maxval] }]]>

Maybe also

(<~) = flip (~>)

for things like `S <~ unS`

, when someone is in a left-to-right mood.

inS = unS ~> S inS2 = unS ~> unS ~> S -- or... inS2' = unS ~> inS

To my eyes, it doesn’t get much better than that.

]]>