packages feed

cookbook-0.1.0.0: Cookbook/Recipes/DiffStat.hs

--Library for determining movement of data within a list. 
--data Stat can have one of 3 forms:
--Less a = Back by a
--Even  = Same position
--Great a = Forward by a
module Cookbook.Recipes.DiffStat(Stat(..),stat,diff,patch) where

import Cookbook.Common
import Cookbook.Ingredients.Lists.Modify
import Cookbook.Ingredients.Lists.Access
import Cookbook.Ingredients.Tupples.Look

import Data.Maybe
data Stat a = Less a | Even |  Great a deriving (Show)

stat :: (Eq a) => [a] -> [a] -> a -> Stat Int
stat x c f
  | f `notElem` x = error "Unique entry found in stat x"
  | f `notElem` c = error "Unique entry found in stat c"
stat x c f
  | diff < 0  = Less diff
  | diff == 0 = Even
  | otherwise = Great diff
  where diff = (pos x f) - (pos c f)

diff :: (Eq a) => [a] -> [a] -> [Stat Int]
diff x [] = []
diff x (c:cs) = stat x (c:cs) c : diff x cs

--The compiler doesn't like this type signature for some reason.
--Here it is anyway, and :t in GHCI can even back it up:
--patch :: (Eq a) => [a] -> [Stat Int] -> [Int] 
patch x c = assemble $ relatdiff posbind c
  where posbind = zip x [0..((length x))]
        
--Get the absolute positions of diff lists.
relatdiff :: (Eq a) => [(a,Int)] -> [Stat Int] -> [(a,Int)]
relatdiff [] _ = []
relatdiff _ [] = []
relatdiff ((a,b):bs) ((Great x):xs) = (a,(b + x)) : relatdiff bs xs
relatdiff ((a,b):bs) ((Less x):xs) = (a,(b - x)) : relatdiff bs xs
relatdiff ((a,b):bs) ((Even):xs) = (a,(b-1)) : relatdiff bs xs

--Assemble a relatdiff list
assemble :: [(a,Int)] -> [a]
assemble x = catMaybes $ map (look (map swp x)) $ qsort (map snd x)