-- | A Transaction consists of a TopLine (information common to all -- postings, such as the DateTime) and of at least two Postings. This -- data relationship is so important and useful that it is expressed -- in these modules. This module has its own functions and re-exports -- functions and types from other modules in this hierarchy. There are -- handy accessor functions for the records within each of the family -- types, but these are not exported due to name conflicts; if you -- want these simply import the necessary module (maybe qualified). module Penny.Lincoln.Family ( -- * Family types F.Family(Family), C.Child(Child), S.Siblings(Siblings), -- * Mapping families F.mapChildrenM, F.mapChildren, F.mapParentM, F.mapParent, -- * Functions to manipulate families children, orphans, adopt, marryWith, marry, divorceWith, divorce, S.collapse ) where import qualified Penny.Lincoln.Family.Family as F import qualified Penny.Lincoln.Family.Child as C import qualified Penny.Lincoln.Family.Siblings as S -- | Gets a family's children. The Child type contains information on -- the parent, and each Child contains information on the other -- Siblings. children :: F.Family p c -> S.Siblings (C.Child p c) children (F.Family p c1 c2 cRest) = S.Siblings fc sc rc where fc = C.Child c1 c2 cRest p sc = C.Child c2 c1 cRest p rc = map toChild rest rest = others cRest toChild (c, cs) = C.Child c c1 (c2:cs) p -- | Separates the children from their parent. orphans :: F.Family p c -> S.Siblings c orphans (F.Family _ c1 c2 cs) = S.Siblings c1 c2 cs -- | Unites a parent and some siblings into one family; the dual of -- orphans. adopt :: p -> S.Siblings c -> F.Family p c adopt p (S.Siblings c1 c2 cs) = F.Family p c1 c2 cs -- | Marries two families into one. This function is rather cruel: if -- one family has more children than the other family, then the extra -- children are discarded. That is, all children must pair one-by-one. marryWith :: (p1 -> p2 -> p3) -> (c1 -> c2 -> c3) -> F.Family p1 c1 -> F.Family p2 c2 -> F.Family p3 c3 marryWith fp fc (F.Family lp lc1 lc2 lcs) (F.Family rp rc1 rc2 rcs) = F.Family (fp lp rp) (fc lc1 rc1) (fc lc2 rc2) (zipWith fc lcs rcs) -- | marryWith a tupling function. marry :: F.Family p1 c1 -> F.Family p2 c2 -> F.Family (p1, p2) (c1, c2) marry = marryWith (,) (,) -- | Splits up a family. divorceWith :: (p1 -> (p2, p3)) -> (c1 -> (c2, c3)) -> F.Family p1 c1 -> (F.Family p2 c2, F.Family p3 c3) divorceWith fp fc (F.Family p c1 c2 cs) = (f2, f3) where f2 = F.Family p2 c21 c22 c2s f3 = F.Family p3 c31 c32 c3s (p2, p3) = fp p (c21, c31) = fc c1 (c22, c32) = fc c2 cps = map fc cs (c2s, c3s) = (map fst cps, map snd cps) -- | divorceWith an untupling function. divorce :: F.Family (p1, p2) (c1, c2) -> (F.Family p1 c1, F.Family p2 c2) divorce = divorceWith id id others :: [a] -> [(a, [a])] others = map yank . allIndexes allIndexes :: [a] -> [(Int, [a])] allIndexes as = zip [0..] (replicate (length as) as) yank :: (Int, [a]) -> (a, [a]) yank (i, as) = let (ys, zs) = splitAt i as in (head zs, ys ++ (tail zs))