module Tile.QList where
import Reactive.Updatable
import Tile.Tilable
import Tile.Atom
data QList d iv v where
QEnd :: QList d iv v
QList :: [Atom d iv v] -> DQ d iv v -> QList d iv v
QRec :: Updatable p d iv => d -> (p -> QList d iv v) -> p -> QList d iv v
size_qlist :: QList t t1 t2 -> Int
size_qlist QEnd = 0
size_qlist (QList _ (DQ _ ql)) = 1 + size_qlist ql
size_qlist (QRec _ _ _) = 1
width_qlist :: QList t t1 t2 -> Int
width_qlist QEnd = 0
width_qlist (QList l (DQ _ ql)) = length l + width_qlist ql
width_qlist (QRec _ _ _) = 0
instance (Show d, Num d, Show v) => Show (QList d iv v) where
show QEnd = "QEnd"
show (QList al dq) = "(QList "++ show al ++" ("++ show dq++"))"
show (QRec _ _ _) = "<QRec>"
instance (Num d, Eq d, POrd d, POrd v) => POrd (QList d iv v) where
pLeq q1 q2 = pLeqQ (reduceQ q1) (reduceQ q2) where
pLeqQ _ QEnd = True
pLeqQ (QRec d f p) x = pLeqQ (stretchQ d (f p)) x
pLeqQ x (QRec d f p) = pLeqQ x (stretchQ d (f p))
pLeqQ (QList al1 dq1) (QList al2 dq2)
= case (pLeq al1 al2) of
True -> pLeq dq1 dq2
False -> False
pLeqQ QEnd (QList [] (DQ _ q)) = pLeq QEnd q
pLeqQ QEnd _ = False
instance (Num d, Eq d, POrd d, POrd v) => Eq (QList d iv v) where
(==) = pOrdEq
data DQ d iv v = DQ d (QList d iv v)
deriving (Show)
instance (Num d, Eq d, POrd d, POrd v) => POrd (DQ d iv v) where
pLeq (DQ d1 q1) (DQ d2 q2)
= case (partialCompare d1 d2) of
Just EQ -> pLeq q1 q2
Just LT -> pLeq (DQ 0 q1) (DQ 0 (QList [] (DQ (d2d1) q2)))
Just GT -> pLeq (DQ 0 (QList [] (DQ (d1d2) q1))) (DQ 0 q2)
Nothing -> error "Tile Partial Order : incomparable duration"
isEmptyQ :: (Num d, Eq d) => QList d iv v -> Bool
isEmptyQ QEnd = True
isEmptyQ (QList [] (DQ _ q)) = isEmptyQ q
isEmptyQ (QList _ _) = False
isEmptyQ (QRec _ f p) = isEmptyQ (f p)
getAtomsQ :: (Num d,Eq d) => QList d iv v -> [Atom d iv v]
getAtomsQ QEnd = []
getAtomsQ (QList l (DQ 0 q)) = l++getAtomsQ q
getAtomsQ (QList l (DQ _ _)) = l
getAtomsQ (QRec d f p)
= getAtomsQ $ stretchQ d (f p)
atomsQ :: (Num d,Eq d) => QList d iv v -> QList d iv v
atomsQ QEnd = QEnd
atomsQ q = QList (getAtomsQ q) (DQ 0 QEnd)
delayToTailQ :: (Num d, Eq d) => QList d iv v -> d
delayToTailQ q
= case dropAtomsQ q of
(QList [] (DQ d _)) -> d
(QEnd) -> 0
_ -> error "delayToTailQ : this should never happend"
tailQ :: (Num d, Eq d) => QList d iv v -> QList d iv v
tailQ QEnd = QEnd
tailQ (QList _ (DQ 0 q)) = tailQ q
tailQ (QList _ (DQ _ q)) = q
tailQ (QRec d f p)
= tailQ $ stretchQ d (f p)
getAllFromAtomsQ :: (Num d, Eq d) => QList d iv v -> [(d,v)]
getAllFromAtomsQ q = fmap getAllA (getAtomsQ q)
dropAtomsQ :: (Num d,Eq d) => QList d iv v -> QList d iv v
dropAtomsQ QEnd = QEnd
dropAtomsQ (QList _ (DQ 0 q)) = dropAtomsQ q
dropAtomsQ (QList _ (DQ d q)) = QList [] (DQ d q)
dropAtomsQ (QRec d f p) = dropAtomsQ $ stretchQ d (f p)
fromValueQ :: (Tilable d v) => v -> QList d iv v
fromValueQ v = QList [fromValueA v] (DQ 0 QEnd)
fromDurationAndValueQ :: (Num d) => d -> v -> QList d iv v
fromDurationAndValueQ d v = QList [Atom d v] (DQ 0 QEnd)
appendQ :: (Num d, Lattice d) =>
[Atom d iv v] -> QList d iv v -> QList d iv v
appendQ al q
= mergeQ (QList al (DQ 0 QEnd),q)
addDelayQ :: (Num d, POrd d) => d -> QList d iv v -> QList d iv v
addDelayQ d q = case partialCompare 0 d of
Just LT -> QList [] (DQ d q)
Just EQ -> q
_ -> error "addDelayQ : Illegal non strictly positive delay arguement"
mergeDQ :: (Num d, Lattice d) => (DQ d iv v,DQ d iv v) -> DQ d iv v
mergeDQ (DQ d1 q1,DQ _ QEnd) = DQ d1 q1
mergeDQ (DQ _ QEnd,DQ d2 q2) = DQ d2 q2
mergeDQ (DQ d1 q1, DQ d2 q2)
= case (partialCompare d1 d2) of
Just GT -> mergeDQ (DQ d2 q2, DQ d1 q1)
Just EQ -> DQ d1 $ mergeQ (q1,q2)
Just LT -> DQ d1 $ insertQ q1 (DQ (d2d1) q2)
Nothing -> let d = meet [d1,d2]
in DQ d $ QRec 1 (\(DQ d1 q1, DQ d2 q2) -> case partialCompare d1 d2 of
Just EQ -> mergeQ (q1,q2)
Just LT -> insertQ q1 (DQ (d2d1) q2)
Just GT -> insertQ q2 (DQ (d1d2) q1)
Nothing -> QEnd)
(DQ d1 q1, DQ d2 q2)
mergeQ :: (Num d, Lattice d) => (QList d iv v,QList d iv v) -> (QList d iv v)
mergeQ (QEnd,q) = q
mergeQ (q,QEnd) = q
mergeQ (QList l1 dq1,QList l2 dq2)
= QList (l1++l2) $ mergeDQ (dq1, dq2)
mergeQ (QRec d1 f1 p1,QRec d2 f2 p2)
= QRec 1 (\(p1,p2) -> mergeQ (stretchQ d1 (f1 p1),stretchQ d2 (f2 p2))) (p1,p2)
mergeQ (qr@(QRec _ _ _),q)
= QRec 1 (\(QRec d f p,q) -> mergeQ (stretchQ d (f p),q)) (qr,q)
mergeQ (q,qr@(QRec _ _ _)) = mergeQ (qr,q)
insertQ :: (Num d, Lattice d) => QList d iv v -> DQ d iv v -> QList d iv v
insertQ QEnd (DQ d q) = QList [] (DQ d q)
insertQ (QList l (DQ d1 q1)) (DQ d2 q2) = QList l (mergeDQ (DQ d1 q1, DQ d2 q2))
insertQ qr@(QRec _ _ _) dq@(DQ _ _)
= QRec 1 (\(QRec df f p,dq) -> insertQ (stretchQ df (f p)) dq) (qr,dq)
stretchQ :: Num d =>
d -> QList d iv v -> QList d iv v
stretchQ _ QEnd = QEnd
stretchQ df (QList al dq) = QList (fmap (stretchA df) al) (stretchDQ df dq)
stretchQ df (QRec d f p) = QRec (df*d) f p
stretchDQ :: Num d =>
d -> DQ d iv v -> DQ d iv v
stretchDQ _ (DQ _ QEnd) = DQ 0 QEnd
stretchDQ dd (DQ d q) = DQ (dd*d) (stretchQ dd q)
reduceQ :: (Num d,POrd d) => QList d iv v -> QList d iv v
reduceQ QEnd = QEnd
reduceQ (QRec d f p) = reduceQ (stretchQ d (f p))
reduceQ (QList [] (DQ d q))
= case partialCompare 0 d of
Just LT -> QList [] (DQ d q)
Just EQ -> reduceQ q
_ -> error "reduceQ : invalid duration in QList (1)"
reduceQ (QList al (DQ d q))
= case partialCompare 0 d of
Just LT -> QList al (DQ d q)
Just EQ -> case reduceQ q of
QEnd -> QList al (DQ 0 QEnd)
QList al1 dq1 -> QList (al++al1) dq1
_ -> error "reduceQ : This should never happen"
_ -> error "reduceQ : invalid duration in QList (2)"
fmapQ :: Num d => (v1 -> v2) -> QList d iv v1 -> QList d iv v2
fmapQ _ QEnd = QEnd
fmapQ f (QList al (DQ d q)) = QList (fmap (fmapA f) al) (DQ d (fmapQ f q))
fmapQ f (QRec d g p) = QRec d (\p -> fmapQ f (g p)) p
instance (Num d) => Functor (QList d iv) where
fmap = fmapQ
fmapDQ :: (Num d) => (d -> d) -> QList d iv v -> QList d iv v
fmapDQ _ QEnd = QEnd
fmapDQ f (QList al (DQ d q)) = QList (fmap (fmapDA f) al) (DQ (f d) $ fmapDQ f q)
fmapDQ f (QRec d g p) = QRec (f d) (\p -> fmapDQ f (g p)) p
fromLeftQ :: QList d iv (Either v1 v2) -> QList d iv v1
fromLeftQ QEnd = QEnd
fromLeftQ (QList al (DQ d q)) = QList [Atom d v | Atom d (Left v) <- al] (DQ d (fromLeftQ q))
fromLeftQ (QRec d f p) = QRec d (\p -> fromLeftQ (f p)) p
fromRightQ :: QList d iv (Either v1 v2) -> QList d iv v2
fromRightQ QEnd = QEnd
fromRightQ (QList al (DQ d q)) = QList [Atom d v | Atom d (Right v) <- al] (DQ d (fromRightQ q))
fromRightQ (QRec d f p) = QRec d (\p -> fromRightQ (f p)) p
takeQ :: (Num d, Lattice d) => d -> QList d iv v -> QList d iv v
takeQ _ QEnd = QEnd
takeQ d q
= case (partialCompare 0 d) of
Just LT -> case q of
(QList al (DQ d1 q1)) -> QList al (DQ d1 $ QRec 1 (\(DQ d q) -> takeQ d q) (DQ (dd1) q1))
(QRec dd f p) -> takeQ d (stretchQ dd (f p))
_ -> error "takeQ : this should never happend"
_ -> QEnd
dropQ :: (Num d, Lattice d) => d -> QList d iv v -> QList d iv v
dropQ _ QEnd = QEnd
dropQ d q
= case partialCompare 0 d of
Just LT
-> case q of
(QList _ (DQ d1 q1))
-> case partialCompare d d1 of
Just GT -> QRec 1 (\(DQ d q) -> dropQ d q) (DQ (dd1) q1)
Just EQ -> q1
_ -> QList [] (DQ (d1 d) q1)
(QRec dd f p) -> dropQ d (stretchQ dd (f p))
_ -> error "dropQ : this should never happend"
_ -> q
split :: Functor f =>
(b -> Bool) -> f b -> f (Either b b)
split f q = fmap
(\v -> case (f v) of
True -> Left v
False -> Right v)
q
reverseQ :: (Num d,Lattice d) => d -> QList d iv v -> (d,QList d iv v)
reverseQ dd q = timedListToQList . reverseTimedList $ qlistToTimedList dd q
qlistToTimedList :: (Num d) => d -> QList d iv v -> [(d,Atom d iv v)]
qlistToTimedList _ QEnd = []
qlistToTimedList dd (QRec d f p) = qlistToTimedList dd (stretchQ d (f p))
qlistToTimedList dd (QList l (DQ d q)) = (map (\a -> (dd,a)) l) ++ qlistToTimedList (dd + d) q
reverseTimedList :: Num d => [(d, Atom d iv v)] -> [(d, Atom d iv v)]
reverseTimedList [] = []
reverseTimedList ((dd,(Atom d v)):l) = (dd,(Atom d v)):reverseTimedList l
timedListToQList :: (Num d, Lattice d) => [(d, Atom d iv v)] -> (d, QList d iv v)
timedListToQList [] = (0,QEnd)
timedListToQList ((dd,a):l)
= let (d,q) = timedListToQList l
in case partialCompare dd d of
Just LT -> (dd,insertQ (QList [a] (DQ 0 QEnd)) (DQ (d dd) q))
Just EQ -> (dd,mergeQ (QList [a] (DQ 0 QEnd),q))
Just GT -> (d,insertQ q (DQ (dd d) (QList [a] (DQ 0 QEnd))))
Nothing -> error "timedListToQList/Reverse tile : non comparable duration"
unfoldQ :: Num d => QList d iv v -> QList d iv v
unfoldQ QEnd = QEnd
unfoldQ (QList al (DQ d q)) = QList al (DQ d (unfoldQ q))
unfoldQ (QRec d f p) = stretchQ d (unfoldQ $ (f p))
instance Updatable (DQ d iv v) d iv where
update (f,nq) (DQ d q) = DQ (f d) $ update (f,nq) q
instance Updatable (QList d iv v) d iv where
update _ QEnd = QEnd
update (f,nq) (QList al (DQ d q)) = QList (update (f,nq) al) (DQ (f d) $ update (f,nq) q)
update (f,nq) (QRec d g p) = QRec (f d) g (update (f,nq) p)
copyAndReplayQ :: (Num d, Lattice d) => d
-> (QList d iv v -> QList d iv v) -> QList d iv v -> QList d iv v
copyAndReplayQ _ _ QEnd = QEnd
copyAndReplayQ d f (QRec dd g p) = QRec dd ((copyAndReplayQ d f).g) p
copyAndReplayQ d f q
= mergeQ (takeQ d q,QList [] (DQ d (QRec 1 (\q-> mergeQ (f (takeQ d q), copyAndReplayQ d f $ dropQ d q)) q)))