----------------------------------------------------------------------------- -- | -- Module : Alib -- Copyright : (C) 2012 Drew Day -- : (C) 1999 Martin Erwig -- License : BSD-style (see the file LICENSE) -- -- Maintainer : Drew Day -- Stability : experimental -- Portability : portable -- -- Code adapted from: -- -- -- Documentation (and further updates in technique) forthcoming. ---------------------------------------------------------------------------- module Alib where import Data.Maybe (fromMaybe) import A import Tree import Graph (Graph,Context,MContext,Node, empty,embed,isEmpty,match,matchAny) import qualified Heap as H import qualified SimpleMap as M ----------------------------------------------------------------------------------------------------------------------------- -- * Constructors (Emitters) and Destructors (Absorbers) -- Functions ----------------------------------------------------------------------------------------------------------------------------- cNat = fromU 0 succ dNat = toU (==0) pred cList = fromB [] (:) dList = toB null head tail cRose = undefined dRose = undefined cProd = fromB (1) (*) dProd = undefined dPqueueH = toB' H.isEmpty H.splitMin dPqueue xs | null xs = UII_U | otherwise = II x (delFst x xs) where x = foldr1 min xs delFst x [] = [] delFst x (y:ys) | y==x = ys | otherwise = y:delFst x ys ----------------------------------------------------------------------------------------------------------------------------- -- Simple (non-parametric) ADTs ----------------------------------------------------------------------------------------------------------------------------- nat :: SymA I Int evn :: SymA I Int halves :: SymA I Int nat2 :: (IxI -> Bool) -> (IxI -> IxI) -> A ( ) ( II Int) IxI rng :: A ( I Int) ( II Int) Int rng' :: A ( ) ( II Int) Int count :: A ( II a Int) I Int prod :: A ( II Int Int) I Int summ :: A ( II Int Int) I Int bool :: BinA Bool Bool boolAnd :: BinA Bool Bool nat = A cNat dNat evn = A (fromU 0 (succ . succ)) (toU (<=0) (pred . pred)) halves = A cNat (toU (==0) (`div` 2) ) rng = A cNat (toB (==0) id pred) rng' = A (\()-> 0 ) (toB (==0) id pred) nat2 p f = A (\_ -> (0,0)) (toB p fst f) count = A (fromB 0 (\_ x -> succ x)) dNat prod = A (fromB 1 (*) ) dNat summ = A (fromB 0 (+) ) dNat graph = A cGraph (toB' isEmpty matchAny) bool = A (fromB False (||)) (toB' not (\_ -> (True,False)) ) boolAnd = A (fromB True (&&)) (toB' id (\_ -> (True,True )) ) ----------------------------------------------------------------------------------------------------------------------------- -- * Familar Data Structures ----------------------------------------------------------------------------------------------------------------------------- set :: (Num a, Eq a) => BinA a [a] list :: BinA a [a] queue :: BinA a [a] pqueue :: Ord a => BinA a [a] pqueueH :: Ord a => BinA a (H.Heap a) jPqueueH :: Ord a => JoinA a H.Heap jQueue :: JoinA a [ ] jList :: JoinA a [ ] jPqueue :: Ord a => JoinA a [ ] bag :: Ord a => BinA a (M.FiniteMap a Int ) arr :: Ord i => (a -> a -> a) -> BinA (i ,a) (M.FiniteMap i a ) fork :: Ord a => A (II a [a]) (IIV [a] ) [a] final :: A (II a (Maybe a)) (Id ) (Maybe a) combine :: A (IIV [a] [a]) (II a ) [a] tree :: SymA (IIV a ) (Tree a ) rose :: SymA (Power a ) (Rose a ) graph :: BinA (Context a b ) (Graph a b) type LinGraph a b = II (Context a b ) (Graph a b) cGraph :: LinGraph a b -> Graph a b ----------------------------------------------------------------------------------------------------------------------------------- -- * 22 data structures in 22 lines ----------------------------------------------------------------------------------------------------------------------------- list = A cList dList rose = A cRose dRose pqueue = A cList dPqueue set = A cList (toB null head rest) queue = A cList (toB null last init) pqueueH = A (fromB H.Empty H.insert ) dPqueueH final = A (fromB Nothing (Just `o` fromMaybe)) (toId id) tree = A (fromT Leaf Branch ) (toT isLeaf key left right) fork = A cList (toT null (sel (==)) (sel (<)) (sel (>))) combine = A (fromT [] append213 ) dList arr f = A (fromB M.emptyFM (accum f) ) (toB' M.isEmptyFM split_arr) bag = A (fromB M.emptyFM add ) (toB' M.isEmptyFM split_bag) forest' = A (fromP Null Nd) (toP' isNull cut ) forest = A (fromId id) (toB null (map root) (concat.map kids)) cGraph = fromB empty embed stack = list jStack = jList jList = joinView list jQueue = joinView queue jPqueue = joinView pqueue jPqueueH = joinView pqueueH ----------------------------------------------------------------------------------------------------------------------------- -- ** Helpers (Selectors, Appends (with swap)) ----------------------------------------------------------------------------------------------------------------------------- sel :: (a -> a -> Bool) -> [a] -> [a] rest :: (Eq a) => [a] -> [a] append213 :: [a] -> [a] -> [a] -> [a] sel f l@(x:_) = filter (flip f x) l rest (x:xs) = filter (/=x) xs append213 y x z = x ++ y ++ z ----------------------------------------------------------------------------------------------------------------------------- -- ** Helpers (Accumulation and Splitting) ----------------------------------------------------------------------------------------------------------------------------- accum :: (Ord o) => (a -> a -> a) -> (o, a) -> M.FiniteMap o a -> M.FiniteMap o a add :: (Ord o, Num a) => o -> M.FiniteMap o a -> M.FiniteMap o a split_bag :: (Ord o, Eq a, Num a) => M.FiniteMap o a -> ( o , M.FiniteMap o a) split_arr :: (Ord o) => M.FiniteMap o a -> ((o,a), M.FiniteMap o a) accum f (i,x) a = M.accumFM a i f x add x b = M.accumFM b x (+) 1 split_bag b = let Just (b'', (x ,c)) = M.splitMinFM b b' = if (==) c 1 then b'' else M.addToFM b'' x (c-1) in (x,b') split_arr a = let Just (a',x) = M.splitMinFM a in (x,a') ----------------------------------------------------------------------------------------------------------------------------- -- * Constructors (Emitters) and Destructors (Absorbers) -- Type Signatures ----------------------------------------------------------------------------------------------------------------------------- -- | construct (resp. destroy) a 'I' of Naturals using 'Int's. cNat :: I Int -> Int dNat :: Int -> I Int -- ^ construct (resp. destroy) a 'I' of Naturals using 'Int's. -- | construct (resp. destroy) a 'II' of @a@s using Lists cList :: II a [a] -> [a] dList :: [a] -> II a [a] -- ^ construct (resp. destroy) a 'II' of @a@s using base Lists dPqueue :: Ord a => [a] -> II a [a] -- ^ destroy priority queue (a 'II' over base Lists) dPqueueH :: Ord a => H.Heap a -> II a (H.Heap a) -- ^ destroy priority queue heap (a 'II' ('Bifunctor') over 'H.Heap's) -- | construct (resp. destroy) a 'II' of two Naturals using 'Int's. cProd :: II Int Int -> Int dProd :: Int -> II Int Int -- ^ construct (resp. destroy) a 'II' of two Naturals using 'Int's. type IxI = (Int, Int) -- ^ a simple type for pairs of integers (not used yet!) ----------------------------------------------------------------------------------------------------------------------------- -- * Rose Trees ----------------------------------------------------------------------------------------------------------------------------- data Rose a = Null | Nd a [Rose a] deriving Show type Forest a = [Rose a] forest' :: PowA a (Rose a) forest :: A (Id [Rose a] ) (II [ a] ) [Rose a] ----------------------------------------------------------------------------------------------------------------------------- -- ** Rose Tree Smart Constructors ----------------------------------------------------------------------------------------------------------------------------- isNull :: Rose a -> Bool cut :: Rose a -> (a,[Rose a]) root :: Rose a -> a kids :: Rose t -> [Rose t] isNull Null = True isNull ____ = False cut (Nd x rs) = (x,rs) root (Nd x __) = x kids (Nd _ rs) = rs ----------------------------------------------------------------------------------------------------------------------------- -- * Linear Graphs (not really complete) ----------------------------------------------------------------------------------------------------------------------------- bufGraph :: (JoinA c f) -> ( c -> Node) -> ( c -> Context a b -> [c] ) -> A () (II (MContext a b)) (f c , Graph a b) bufGraph (A c d) f h = A (\_ -> (c UII_U,empty)) explore where explore (b,g) = case d b of UII_U -> UII_U II x b' | isEmpty g -> UII_U | otherwise -> II ctx (c (II s b'), g' ) where ( ctx , g' ) = match (f x) g s = maybe [] (h x) ctx ----------------------------------------------------------------------------------------------------------------------------- -- * Utilities ----------------------------------------------------------------------------------------------------------------------------- q1 :: ( t, x, y, z) -> t q2 :: ( t, x, y, z) -> x q23 :: ( t, x, y, z) -> (x,y) q4 :: ( t, x, y, z) -> z q1 ( t, _, _, _) = t q2 ( _, x, _, _) = x q23 ( _, x, y, _) = (x,y) q4 ( _, _, _, z) = z -- uncurrying process: -- (\f g -> (f . g) ) :: forall a b (f :: * -> *). (Functor f) => (a -> b) -> f a -> f b -- (\f g -> (f . (uncurry g)) ) :: forall a b a1 b1. (a -> b) -> (a1 -> b1 -> a) -> (a1, b1) -> b -- (\f g -> curry (f . (uncurry g)) ) :: forall c a b c1. (c1 -> c) -> (a -> b -> c1) -> a -> b -> c -- | curried composition -- --o :: forall a f g b. (b -> a) -> (f -> g -> b) -> f -> g -> a f `o` g = curry (f . (uncurry g)) ----------------------------------------------------------------------------------------------------------------------------- -- * Extra! (perhaps not needed) ----------------------------------------------------------------------------------------------------------------------------- -- Perhaps I'll find use for this later (to shorten Nothing) data NoK o = No | OK o infixr 8 >< infixr 8 /\ (f >< g) (x,y) = (f x,g y) -- never used here (f /\ g) x = (f x,g x) -- never used here