module Music.Theory.Time.Seq where
import Data.Function
import Data.List
import qualified Data.List.Ordered as O
import qualified Data.Map as M
import Data.Maybe
import Data.Ratio
import Safe
import Music.Theory.Function
import qualified Music.Theory.List as T
import qualified Music.Theory.Math as T
import qualified Music.Theory.Ord as T
import qualified Music.Theory.Tuple as T
type Useq t a = (t,[a])
type Dseq t a = [(t,a)]
type Iseq t a = [(t,a)]
type Pseq t a = [((t,t,t),a)]
type Tseq t a = [(t,a)]
type Wseq t a = [((t,t),a)]
pseq_zip :: [t] -> [t] -> [t] -> [a] -> Pseq t a
pseq_zip l o f a = (zip (zip3 l o f) a)
wseq_zip :: [t] -> [t] -> [a] -> Wseq t a
wseq_zip t d a = (zip (zip t d) a)
seq_tspan :: Num n => (t -> n) -> (t -> n) -> [(t,a)] -> (n,n)
seq_tspan st et sq =
(maybe 0 (st . fst) (headMay sq)
,maybe 0 (et . fst) (lastMay sq))
tseq_tspan :: Num t => Tseq t a -> (t,t)
tseq_tspan = seq_tspan id id
wseq_tspan :: Num t => Wseq t a -> (t,t)
wseq_tspan = seq_tspan fst (uncurry (+))
wseq_start :: Num t => Wseq t a -> t
wseq_start = fst . wseq_tspan
wseq_end :: Num t => Wseq t a -> t
wseq_end = snd . wseq_tspan
dseq_dur :: Num t => Dseq t a -> t
dseq_dur = sum . map fst
iseq_dur :: Num t => Iseq t a -> t
iseq_dur = sum . map fst
pseq_dur :: Num t => Pseq t a -> t
pseq_dur = sum . map (T.t3_third . fst)
tseq_dur :: Num t => Tseq t a -> t
tseq_dur = uncurry subtract . tseq_tspan
wseq_dur :: Num t => Wseq t a -> t
wseq_dur = uncurry subtract . wseq_tspan
wseq_until :: Ord t => t -> Wseq t a -> Wseq t a
wseq_until tm = takeWhile (\((t0,_),_) -> t0 <= tm)
wseq_twindow :: (Num t, Ord t) => (t,t) -> Wseq t a -> Wseq t a
wseq_twindow (w0,w1) =
let f (st,du) = w0 <= st && (st + du) <= w1
in wseq_tfilter f . wseq_until w1
wseq_at :: (Num t,Ord t) => Wseq t a -> t -> Wseq t a
wseq_at sq tm =
let sel ((t0,t1),_) = t0 <= tm && tm < (t0 + t1)
end ((t0,_),_) = t0 <= tm
in filter sel (takeWhile end sq)
wseq_at_window :: (Num t, Ord t) => Wseq t a -> (t,t) -> Wseq t a
wseq_at_window sq (w0,w1) =
let f (t0,t1) t = t0 <= t && t < t1
g (st,du) = let w = (st,st + du) in f w w0 || f w w1
in wseq_tfilter g (wseq_until w1 sq)
dseq_append :: Dseq t a -> Dseq t a -> Dseq t a
dseq_append = (++)
iseq_append :: Iseq t a -> Iseq t a -> Iseq t a
iseq_append = (++)
pseq_append :: Pseq t a -> Pseq t a -> Pseq t a
pseq_append = (++)
tseq_merge :: Ord t => Tseq t a -> Tseq t a -> Tseq t a
tseq_merge = O.mergeBy (compare `on` fst)
tseq_merge_by :: Ord t => T.Compare_F a -> Tseq t a -> Tseq t a -> Tseq t a
tseq_merge_by cmp = T.merge_by_two_stage fst cmp snd
tseq_merge_resolve :: Ord t => (a -> a -> a) -> Tseq t a -> Tseq t a -> Tseq t a
tseq_merge_resolve f =
let cmp = compare `on` fst
g (t,p) (_,q) = (t,f p q)
in T.merge_by_resolve g cmp
w_compare :: Ord t => ((t,t),a) -> ((t,t),a) -> Ordering
w_compare ((t1,d1),_) ((t2,d2),_) =
case compare t1 t2 of
EQ -> compare d1 d2
r -> r
wseq_merge :: Ord t => Wseq t a -> Wseq t a -> Wseq t a
wseq_merge = O.mergeBy (compare `on` (fst . fst))
wseq_merge_set :: Ord t => [Wseq t a] -> Wseq t a
wseq_merge_set = T.merge_set_by w_compare
tseq_lookup_window_by :: (t -> t -> Ordering) -> Tseq t e -> t -> (Maybe (t,e),Maybe (t,e))
tseq_lookup_window_by cmp =
let recur l sq t =
case sq of
[] -> (l,Nothing)
(t',e):sq' -> case cmp t t' of
LT -> (l,Just (t',e))
_ -> case sq' of
[] -> (Just (t',e),Nothing)
(t'',e'):_ -> case cmp t t'' of
LT -> (Just (t',e),Just (t'',e'))
_ -> recur (Just (t',e)) sq' t
in recur Nothing
tseq_lookup_active_by :: (t -> t -> Ordering) -> Tseq t e -> t -> Maybe e
tseq_lookup_active_by cmp sq = fmap snd . fst . tseq_lookup_window_by cmp sq
tseq_lookup_active :: Ord t => Tseq t e -> t -> Maybe e
tseq_lookup_active = tseq_lookup_active_by compare
tseq_lookup_active_by_def :: e -> (t -> t -> Ordering) -> Tseq t e -> t -> e
tseq_lookup_active_by_def def cmp sq = fromMaybe def . tseq_lookup_active_by cmp sq
tseq_lookup_active_def :: Ord t => e -> Tseq t e -> t -> e
tseq_lookup_active_def def = tseq_lookup_active_by_def def compare
data Interpolation_T = None | Linear
deriving (Eq,Enum,Show)
type Lseq t a = Tseq (t,Interpolation_T) a
lerp :: (Fractional t,Real t,Fractional e) => (t,e) -> (t,e) -> t -> e
lerp (t0,e0) (t1,e1) t =
let n = t1 t0
m = t t0
l = m / n
in realToFrac l * (e1 e0) + e0
lseq_tmap :: (t -> t') -> Lseq t a -> Lseq t' a
lseq_tmap f = let g ((t,i),e) = ((f t,i),e) in map g
lseq_lookup :: (Fractional t,Real t,Fractional e) => (t -> t -> Ordering) -> Lseq t e -> t -> Maybe e
lseq_lookup cmp sq t =
case tseq_lookup_window_by (cmp `on` fst) sq (t,undefined) of
(Nothing,_) -> Nothing
(Just ((_,None),e),_) -> Just e
(Just ((t0,Linear),e0),Just ((t1,_),e1)) -> Just (lerp (t0,e0) (t1,e1) t)
_ -> Nothing
lseq_lookup_err :: (Fractional t,Real t,Fractional e) => (t -> t -> Ordering) -> Lseq t e -> t -> e
lseq_lookup_err cmp sq = fromMaybe (error "lseq_lookup") . lseq_lookup cmp sq
seq_tmap :: (t -> t') -> [(t,a)] -> [(t',a)]
seq_tmap f = map (\(p,q) -> (f p,q))
seq_map :: (b -> c) -> [(a,b)] -> [(a,c)]
seq_map f = map (\(p,q) -> (p,f q))
seq_bimap :: (t -> t') -> (e -> e') -> [(t,e)] -> [(t',e')]
seq_bimap f g = map (\(p,q) -> (f p,g q))
seq_tfilter :: (t -> Bool) -> [(t,a)] -> [(t,a)]
seq_tfilter f = filter (f . fst)
seq_filter :: (b -> Bool) -> [(a,b)] -> [(a,b)]
seq_filter f = filter (f . snd)
seq_find :: (a -> Bool) -> [(t,a)] -> Maybe (t,a)
seq_find f = let f' (_,a) = f a in find f'
seq_map_maybe :: (p -> Maybe q) -> [(t,p)] -> [(t,q)]
seq_map_maybe f =
let g (t,e) = maybe Nothing (\e' -> Just (t,e')) (f e)
in mapMaybe g
seq_cat_maybes :: [(t,Maybe q)] -> [(t,q)]
seq_cat_maybes = seq_map_maybe id
seq_changed_by :: (a -> a -> Bool) -> [(t,a)] -> [(t,Maybe a)]
seq_changed_by f l =
let recur z sq =
case sq of
[] -> []
(t,e):sq' -> if f e z
then (t,Nothing) : recur z sq'
else (t,Just e) : recur e sq'
in case l of
[] -> []
(t,e) : l' -> (t,Just e) : recur e l'
seq_changed :: Eq a => [(t,a)] -> [(t,Maybe a)]
seq_changed = seq_changed_by (==)
wseq_tmap_st :: (t -> t) -> Wseq t a -> Wseq t a
wseq_tmap_st f = let g (t,d) = (f t,d) in seq_tmap g
wseq_tmap_dur :: (t -> t) -> Wseq t a -> Wseq t a
wseq_tmap_dur f = let g (t,d) = (t,f d) in seq_tmap g
seq_partition :: Ord v => (a -> v) -> [(t,a)] -> [(v,[(t,a)])]
seq_partition voice sq =
let assign m (t,a) = M.insertWith (++) (voice a) [(t,a)] m
from_map = sortOn fst .
map (\(v,l) -> (v,reverse l)) .
M.toList
in from_map (foldl assign M.empty sq)
tseq_partition :: Ord v => (a -> v) -> Tseq t a -> [(v,Tseq t a)]
tseq_partition = seq_partition
wseq_partition :: Ord v => (a -> v) -> Wseq t a -> [(v,Wseq t a)]
wseq_partition = seq_partition
coalesce_f :: (t -> t -> Bool) -> (t -> t -> t) -> [t] -> [t]
coalesce_f dec_f jn_f z =
let recur p l =
case l of
[] -> [p]
c:l' -> if dec_f p c
then recur (jn_f p c) l'
else p : recur c l'
in case z of
[] -> []
e0:z' -> recur e0 z'
coalesce_m :: Monoid t => (t -> t -> Bool) -> [t] -> [t]
coalesce_m dec_f = coalesce_f dec_f mappend
seq_coalesce :: Num t => (a -> a -> Bool) -> (a -> a -> a) -> [(t,a)] -> [(t,a)]
seq_coalesce dec_f jn_f =
let dec_f' = dec_f `on` snd
jn_f' (t1,a1) (t2,a2) = (t1 + t2,jn_f a1 a2)
in coalesce_f dec_f' jn_f'
dseq_coalesce :: Num t => (a -> a -> Bool) -> (a -> a -> a) -> Dseq t a -> Dseq t a
dseq_coalesce = seq_coalesce
dseq_coalesce' :: Num t => (a -> a -> Bool) -> Dseq t a -> Dseq t a
dseq_coalesce' eq =
let f l = let (t,e:_) = unzip l in (sum t,e)
in map f . groupBy (eq `on` snd)
iseq_coalesce :: Num t => (a -> a -> Bool) -> (a -> a -> a) -> Iseq t a -> Iseq t a
iseq_coalesce = seq_coalesce
seq_tcoalesce :: (t -> t -> Bool) -> (a -> a -> a) -> [(t,a)] -> [(t,a)]
seq_tcoalesce eq_f jn_f =
let dec_f = eq_f `on` fst
jn_f' (t,a1) (_,a2) = (t,jn_f a1 a2)
in coalesce_f dec_f jn_f'
tseq_tcoalesce :: Eq t => (a -> a -> a) -> Tseq t a -> Tseq t a
tseq_tcoalesce = seq_tcoalesce (==)
wseq_tcoalesce :: ((t,t) -> (t,t) -> Bool) -> (a -> a -> a) -> Wseq t a -> Wseq t a
wseq_tcoalesce = seq_tcoalesce
group_f :: (Eq t,Num t) => (t -> t -> Bool) -> [(t,a)] -> [(t,[a])]
group_f cmp =
let f l = let (t,a) = unzip l
in case t of
[] -> error "group_f: []?"
t0:_ -> (t0,a)
in map f . groupBy (cmp `on` fst)
tseq_group :: (Eq t,Num t) => Tseq t a -> Tseq t [a]
tseq_group = group_f (==)
iseq_group :: (Eq t,Num t) => Iseq t a -> Iseq t [a]
iseq_group = group_f (\_ d -> d == 0)
wseq_fill_dur :: Num t => Wseq t a -> Wseq t a
wseq_fill_dur l =
let f (((t1,_),e),((t2,_),_)) = ((t1,t2t1),e)
in map f (T.adj2 1 l) ++ [last l]
dseq_lcm :: Dseq Rational e -> Integer
dseq_lcm = foldl1 lcm . map (denominator . fst)
dseq_set_whole :: [Dseq Rational e] -> [Dseq Integer e]
dseq_set_whole sq =
let m = maximum (map dseq_lcm sq)
t_f n = T.rational_whole_err (n * fromIntegral m)
in map (dseq_tmap t_f) sq
tseq_latch :: Ord t => a -> Tseq t a -> [t] -> Tseq t a
tseq_latch def sq t =
case (sq,t) of
([],_) -> zip t (repeat def)
(_,[]) -> []
((sq_t,sq_e):sq',t0:t') -> case compare sq_t t0 of
LT -> (sq_t,sq_e) : tseq_latch sq_e sq' t
EQ -> (sq_t,sq_e) : tseq_latch sq_e sq' t'
GT -> (t0,def) : tseq_latch def sq t'
wseq_sort :: Ord t => Wseq t a -> Wseq t a
wseq_sort = sortBy (compare `on` (fst . fst))
wseq_discard_dur :: Wseq t a -> Tseq t a
wseq_discard_dur = let f ((t,_),e) = (t,e) in map f
wseq_overlap_f :: (Eq e,Ord t,Num t) =>
(e -> e -> Bool) -> (t -> t) -> ((t,t),e) -> Wseq t e -> Maybe (Wseq t e)
wseq_overlap_f eq_fn dur_fn ((t,d),a) sq =
case find (eq_fn a . snd) sq of
Nothing -> Nothing
Just ((t',d'),a') ->
if t == t'
then if d <= d'
then Just sq
else Just (((t,d),a) : delete ((t',d'),a') sq)
else if t' < t + d
then Just (((t,dur_fn (t' t)),a) : sq)
else Nothing
wseq_has_overlaps :: (Ord t, Num t, Eq e) => (e -> e -> Bool) -> Wseq t e -> Bool
wseq_has_overlaps eq_fn =
let recur sq =
case sq of
[] -> False
h:sq' ->
case wseq_overlap_f eq_fn id h sq' of
Nothing -> recur sq'
Just _ -> True
in recur
wseq_remove_overlaps :: (Eq e,Ord t,Num t) =>
(e -> e -> Bool) -> (t -> t) -> Wseq t e -> Wseq t e
wseq_remove_overlaps eq_fn dur_fn =
let recur sq =
case sq of
[] -> []
h:sq' ->
case wseq_overlap_f eq_fn dur_fn h sq' of
Nothing -> h : recur sq'
Just sq'' -> recur sq''
in recur
seq_unjoin :: [(t,[e])] -> [(t,e)]
seq_unjoin = let f (t,e) = zip (repeat t) e in concatMap f
wseq_unjoin :: Wseq t [e] -> Wseq t e
wseq_unjoin = seq_unjoin
wseq_shift :: Num t => t -> Wseq t a -> Wseq t a
wseq_shift i = wseq_tmap_st (+ i)
wseq_append :: Num t => Wseq t a -> Wseq t a -> Wseq t a
wseq_append p q = p ++ wseq_shift (wseq_end p) q
wseq_concat :: Num t => [Wseq t a] -> Wseq t a
wseq_concat = foldl1 wseq_append
data Begin_End a = Begin a | End a deriving (Eq,Show)
begin_end_map :: (t -> u) -> Begin_End t -> Begin_End u
begin_end_map f x =
case x of
Begin a -> Begin (f a)
End a -> End (f a)
cmp_begin_end :: Begin_End a -> Begin_End b -> Ordering
cmp_begin_end p q =
case (p,q) of
(Begin _,End _) -> LT
(Begin _,Begin _) -> EQ
(End _,End _) -> EQ
(End _,Begin _) -> GT
either_to_begin_end :: Either a a -> Begin_End a
either_to_begin_end p =
case p of
Left a -> Begin a
Right a -> End a
begin_end_to_either :: Begin_End a -> Either a a
begin_end_to_either p =
case p of
Begin a -> Left a
End a -> Right a
begin_end_partition :: [Begin_End a] -> ([a],[a])
begin_end_partition =
let f e (p,q) = case e of
Begin x -> (x:p,q)
End x -> (p,x:q)
in foldr f ([],[])
begin_end_track :: Eq a => [a] -> Begin_End a -> [a]
begin_end_track st e =
case e of
Begin x -> x : st
End x -> delete x st
wseq_begin_end :: (Num t, Ord t) => Wseq t a -> Tseq t (Begin_End a)
wseq_begin_end sq =
let f ((t,d),a) = [(t,Begin a),(t + d,End a)]
g l =
case l of
[] -> []
e:l' -> tseq_merge_by (T.ord_invert .: cmp_begin_end) e (g l')
in g (map f sq)
wseq_begin_end_either :: (Num t, Ord t) => Wseq t a -> Tseq t (Either a a)
wseq_begin_end_either = tseq_map begin_end_to_either . wseq_begin_end
wseq_begin_end_f :: (Ord t,Num t) => (a -> b) -> (a -> b) -> Wseq t a -> Tseq t b
wseq_begin_end_f f g = tseq_map (either f g) . wseq_begin_end_either
tseq_begin_end_accum :: Eq a => Tseq t [Begin_End a] -> Tseq t ([a],[a],[a])
tseq_begin_end_accum =
let f st (t,x) =
let (b,e) = begin_end_partition x
st' = foldl begin_end_track st x
in (st',(t,(b,e,st \\ e)))
in snd . mapAccumL f []
tseq_accumulate :: Eq a => Tseq t [Begin_End a] -> Tseq t [a]
tseq_accumulate =
let f st (t,e) =
let g st' = (st',(t,st'))
in g (foldl begin_end_track st e)
in snd . mapAccumL f []
wseq_accumulate :: (Eq a,Ord t,Num t) => Wseq t a -> Tseq t [a]
wseq_accumulate = tseq_accumulate . tseq_group . wseq_begin_end
tseq_begin_end_to_wseq :: Num t => (a -> a -> Bool) -> Tseq t (Begin_End a) -> Wseq t a
tseq_begin_end_to_wseq cmp =
let cmp' x e =
case e of
End x' -> cmp x x'
_ -> False
f e r = case seq_find (cmp' e) r of
Nothing -> error "tseq_begin_end_to_wseq: no matching end?"
Just (t,_) -> t
go sq = case sq of
[] -> []
(_,End _) : sq' -> go sq'
(t,Begin e) : sq' -> let t' = f e sq' in ((t,t' t),e) : go sq'
in go
useq_to_dseq :: Useq t a -> Dseq t a
useq_to_dseq (t,e) = zip (repeat t) e
useq_to_wseq :: Num t => t -> Useq t a -> Wseq t a
useq_to_wseq t0 = dseq_to_wseq t0 . useq_to_dseq
dseq_to_tseq :: Num t => t -> a -> Dseq t a -> Tseq t a
dseq_to_tseq t0 nil sq =
let (d,a) = unzip sq
t = T.dx_d t0 d
a' = a ++ [nil]
in zip t a'
dseq_to_tseq_last :: Num t => t -> Dseq t a -> Tseq t a
dseq_to_tseq_last t0 sq = dseq_to_tseq t0 (snd (last sq)) sq
pseq_to_wseq :: Num t => t -> Pseq t a -> Wseq t a
pseq_to_wseq t0 sq =
let (p,a) = unzip sq
(_,d,f) = unzip3 p
t = T.dx_d t0 f
in wseq_zip t d a
tseq_to_dseq :: (Ord t,Num t) => a -> Tseq t a -> Dseq t a
tseq_to_dseq empty sq =
let (t,a) = unzip sq
d = T.d_dx t
in case t of
[] -> []
t0:_ -> if t0 > 0 then (t0,empty) : zip d a else zip d a
tseq_to_wseq :: Num t => Maybe (a -> t) -> Tseq t a -> Wseq t a
tseq_to_wseq dur_f sq =
let (t,a) = unzip sq
d = case dur_f of
Just f -> map f (fst (T.separate_last a))
Nothing -> T.d_dx t
in wseq_zip t d a
tseq_to_iseq :: Num t => Tseq t a -> Dseq t a
tseq_to_iseq =
let recur n p =
case p of
[] -> []
(t,e):p' -> (t n,e) : recur t p'
in recur 0
dseq_to_wseq :: Num t => t -> Dseq t a -> Wseq t a
dseq_to_wseq t0 sq =
let (d,a) = unzip sq
t = T.dx_d t0 d
in zip (zip t d) a
wseq_to_dseq :: (Num t,Ord t) => a -> Wseq t a -> Dseq t a
wseq_to_dseq empty sq =
let f (((st0,d),e),((st1,_),_)) =
let d' = st1 st0
in case compare d d' of
LT -> [(d,e),(d'd,empty)]
EQ -> [(d,e)]
GT -> [(d',e)]
((_,dN),eN) = last sq
r = concatMap f (T.adj2 1 sq) ++ [(dN,eN)]
in case sq of
((st,_),_):_ -> if st > 0 then (st,empty) : r else r
[] -> error "wseq_to_dseq"
dseql_to_tseql :: Num t => t -> [Dseq t a] -> (t,[Tseq t a])
dseql_to_tseql =
let f z dv =
let (tm,el) = unzip dv
(z',r) = T.dx_d' z tm
in (z',zip r el)
in mapAccumL f
wseq_cycle' :: Num t => Wseq t a -> [Wseq t a]
wseq_cycle' sq =
let (_,et) = wseq_tspan sq
t_sq = iterate (+ et) 0
in map (\x -> wseq_tmap (\(t,d) -> (x + t,d)) sq) t_sq
wseq_cycle :: Num t => Wseq t a -> Wseq t a
wseq_cycle = concat . wseq_cycle'
wseq_cycle_n :: Num t => Int -> Wseq t a -> Wseq t a
wseq_cycle_n n = concat . take n . wseq_cycle'
wseq_cycle_until :: (Num t,Ord t) => t -> Wseq t a -> Wseq t a
wseq_cycle_until et = wseq_until et . wseq_cycle
dseq_tmap :: (t -> t') -> Dseq t a -> Dseq t' a
dseq_tmap = seq_tmap
pseq_tmap :: ((t,t,t) -> (t',t',t')) -> Pseq t a -> Pseq t' a
pseq_tmap = seq_tmap
tseq_tmap :: (t -> t') -> Dseq t a -> Dseq t' a
tseq_tmap = seq_tmap
tseq_bimap :: (t -> t') -> (e -> e') -> Tseq t e -> Tseq t' e'
tseq_bimap = seq_bimap
wseq_tmap :: ((t,t) -> (t',t')) -> Wseq t a -> Wseq t' a
wseq_tmap = seq_tmap
dseq_map :: (a -> b) -> Dseq t a -> Dseq t b
dseq_map = seq_map
pseq_map :: (a -> b) -> Pseq t a -> Pseq t b
pseq_map = seq_map
tseq_map :: (a -> b) -> Tseq t a -> Tseq t b
tseq_map = seq_map
wseq_map :: (a -> b) -> Wseq t a -> Wseq t b
wseq_map = seq_map
dseq_tfilter :: (t -> Bool) -> Dseq t a -> Dseq t a
dseq_tfilter = seq_tfilter
iseq_tfilter :: (t -> Bool) -> Iseq t a -> Iseq t a
iseq_tfilter = seq_tfilter
pseq_tfilter :: ((t,t,t) -> Bool) -> Pseq t a -> Pseq t a
pseq_tfilter = seq_tfilter
tseq_tfilter :: (t -> Bool) -> Tseq t a -> Tseq t a
tseq_tfilter = seq_tfilter
wseq_tfilter :: ((t,t) -> Bool) -> Wseq t a -> Wseq t a
wseq_tfilter = seq_tfilter
dseq_filter :: (a -> Bool) -> Dseq t a -> Dseq t a
dseq_filter = seq_filter
iseq_filter :: (a -> Bool) -> Iseq t a -> Iseq t a
iseq_filter = seq_filter
pseq_filter :: (a -> Bool) -> Pseq t a -> Pseq t a
pseq_filter = seq_filter
tseq_filter :: (a -> Bool) -> Tseq t a -> Tseq t a
tseq_filter = seq_filter
wseq_filter :: (a -> Bool) -> Wseq t a -> Wseq t a
wseq_filter = seq_filter
wseq_map_maybe :: (a -> Maybe b) -> Wseq t a -> Wseq t b
wseq_map_maybe = seq_map_maybe
wseq_cat_maybes :: Wseq t (Maybe a) -> Wseq t a
wseq_cat_maybes = seq_cat_maybes