module TechnicalIndicators.SMA (sma) where

import Control.Applicative ((<$>), (<*>))
import Control.Arrow ((***))
import Data.List (tails, unfoldr)
import Data.Maybe (isNothing, fromJust)

-- | Global Proposition : We suggest that the list of key value pair has been sorted by key.
--   This module just only calculate simple moving value.

sma :: Fractional v => Int -> [(k, Maybe v)] -> [(k, v)]
sma n = uncurry zip . (drop (n-1) *** map (average . take n) . tails) . unzip . cleansing

average :: Fractional a => [a] -> a
average xs = s / l
    where
      (s, l) = foldr (\a (x, y) -> (a + x, 1 + y)) (0,0) xs

cleansing :: [(k, Maybe v)] -> [(k, v)]
cleansing = uncurry zip . (id *** repair) . unzip . dropWhile (isNothing . snd)

-- | This function expect the argument list has Just value as head element.
repair :: [Maybe a] -> [a]
repair xxs@(Just x:xs) = unfoldr step (x, xxs)
    where
      step (old, []) = Nothing
      step (old, x:xs) = let just = (,) <*> (,xs) in Just $ maybe (just old) just x
repair [] = []
repair (Nothing:xs) = error "'repair' expect Just value as head of argument list."

module TechnicalIndicators.SMA (sma) where

import Control.Applicative ((<$>), (<*>))
import Data.List (tails, unfoldr)

cross (f, g) (x, y) = (f x, g y)

-- | Global Proposition : We suggest that the list of key value pair has been sorted by key.
--   This module just only calculate simple moving value.

sma :: Fractional v => Int -> [(k, v)] -> [(k, v)]
sma n = uncurry zip . cross (drop (n-1), map (average . take n) . tails) . unzip

average :: Fractional a => [a] -> a
average xs = s / l
    where
      (s, l) = foldr (\a (x, y) -> (a + x, 1 + y)) (0,0) xs

sanitize :: [Maybe a] -> [Maybe a]
sanitize xs = unfoldr f (Nothing, xs)
  where
    f (old, []) = Nothing
    f (old, x:xs) = Just $ maybe nothing just x
        where
          nothing = (old, (old, xs))
          just x' = let new = Just x' in (new, (new, xs))

Revert a combination of next 3 commits.
Revert a combination of next 3 commits.

Revert "[Comment] excuse for repair spec"
This reverts commit c7215083bfb48d280791f7c5153869084195cb5a.
Revert "[Refactor] arrange repair"
This reverts commit 0d61831feaa4924fcc6e888a1200392d8dbc1e2a.
Revert "cleansing and repair the argument list (key value pair list)"
This reverts commit e5939a3d6480599fa089b2e9e6444c30663784e0.
