
Nathan Hüsken
Hey,
I am working a lot with timeseries (with instances at discrete moments) of doubles. So I use [Double].
You may want to consider using a more efficient type than [Double] if your data is at all large. Unless you really want the laziness that lists offer you might be better off using vectors.
Now I want to be able to do stuff like
timeSeries3 = timeSeries1 + timeSeries2
So I was thinking, I create a newtype
newtype TimeSeries a = TimeSeries [a]
Now, can I somehow autoderive List, Monad, MonadPlus for TimeSeries?
As far as I'm aware, List is not a typeclass. You can conveniently derive newtype instances with GeneralizedNewtypeDeriving[1] in most cases. That being said you need to decide what sort of semantics you want your type to have. In the case of Appplicative, you have a choice between ZipList (which would make point-wise operations straightforward) and standard list (making non-determinism straightforward). Applicative is tricky in the case of vector-like types as you don't know what length you want your timeseries to be. In the list case you can simply produce a non-terminating series. One way around this (although perhaps not the best way) would be to introduce a constructor to represent a homogenous timeseries. This might look something like, import qualified Data.Vector as V import Control.Applicative data TimeSeries a = Pure a | Moments (V.Vector a) deriving (Show) instance Functor TimeSeries where fmap f (Pure a) = Pure (f a) fmap f (Moments as) = Moments (fmap f as) instance Applicative TimeSeries where pure = Pure Pure a <*> Pure b = Pure (a b) Pure a <*> Moments bs = Moments $ fmap a bs Moments as <*> Pure b = Moments $ fmap ($ b) as Moments as <*> Moments bs = Moments $ V.zipWith ($) as bs fromList :: [a] -> TimeSeries a fromList = Moments . V.fromList times :: TimeSeries Int times = fromList [1,5,9,2,5] main = do print $ (+) <$> pure 4 <*> times Of course, this presents the possibility of trying to perform a point-wise operation on differently sizes series. Zip-like functions will typically truncate their output to the shortest of their arguments, opening the possibility for silent data loss. One (hacky) way around this would be to accept a partial Applicative instance, returning bottom in the event of incompatible series. Another approach would be to parametrize the type on the length of the series with type-level naturals[3]. This still leaves open the possibility of performing actions on series of incompatible stride or offset, but at least you can be certain your series are of compatible shapes.
Also I would like to derive from Num. Most of the things can be done pointwise!
What about fromInteger??? Should that just be a list with one element? Or does it simple not make sense?
I probably wouldn't use the Num typeclass here for this reason, among others. If you give you type the right Applicative instance the operations you are after should be easily performed. Cheers, - Ben [1] http://www.haskell.org/ghc/docs/7.4.1/html/users_guide/deriving.html [2] http://hackage.haskell.org/package/linear