event-list-0.0.8: src/Data/AlternatingList/List/Mixed.hs
{- |
Copyright : (c) Henning Thielemann 2007
Maintainer : haskell@henning-thielemann.de
Stability : stable
Portability : Haskell 98
Functions that combine both data types,
'Data.AlternatingList.List.Disparate.T' and
'Data.AlternatingList.List.Uniform.T'
-}
module Data.AlternatingList.List.Mixed (
consFirst, consSecond, (./), (/.),
snocFirst, snocSecond,
viewL, viewFirstL, viewSecondL,
viewR, viewFirstR, viewSecondR,
switchL, switchFirstL, switchSecondL,
switchR, switchFirstR, switchSecondR,
mapFirstL, mapFirstHead, mapFirstTail,
mapSecondL, mapSecondHead, mapSecondTail,
mapFirstR, mapFirstLast, mapFirstInit,
mapSecondR, mapSecondLast, mapSecondInit,
appendUniformUniform, appendDisparateUniform, appendUniformDisparate,
concatUniform, concatDisparate,
splitAtDisparateUniform, splitAtUniformDisparate, splitAtUniformUniform,
takeDisparate, takeUniform, dropDisparate, dropUniform,
{- spanFirst, spanSecond, spanDisparate, -}
) where
import qualified Data.AlternatingList.List.Disparate as Disp
import qualified Data.AlternatingList.List.Uniform as Uniform
import Data.AlternatingList.List.Uniform (mapSecondHead)
import qualified Control.Monad as Monad
import Data.EventList.Utility (mapPair, mapFst, mapSnd)
import Prelude hiding
(null, foldr, map, concat, sequence, sequence_, mapM, mapM_)
infixr 5 ./, /.
(/.) :: a -> Uniform.T a b -> Disp.T a b
(/.) = consFirst
(./) :: b -> Disp.T a b -> Uniform.T a b
(./) = consSecond
consFirst :: a -> Uniform.T a b -> Disp.T a b
consFirst a ~(Uniform.Cons b xs) = Disp.cons a b xs
consSecond :: b -> Disp.T a b -> Uniform.T a b
consSecond = Uniform.Cons
snocFirst :: Uniform.T a b -> a -> Disp.T b a
snocFirst xs = appendUniformUniform xs . Uniform.singleton
-- snocFirst xs a = Uniform.foldr consSecond consFirst (Uniform.singleton a) xs
snocSecond :: Disp.T b a -> b -> Uniform.T a b
snocSecond xs = appendDisparateUniform xs . Uniform.singleton
-- snocSecond xs b = Disp.foldr consSecond consFirst (Uniform.singleton b) xs
viewL :: Uniform.T a b -> (b, Maybe (a, Uniform.T a b))
viewL = mapSnd viewFirstL . viewSecondL
viewFirstL :: Disp.T a b -> Maybe (a, Uniform.T a b)
viewFirstL =
Monad.liftM (\((a,b), xs) -> (a, consSecond b xs)) . Disp.viewL
viewSecondL :: Uniform.T a b -> (b, Disp.T a b)
viewSecondL (Uniform.Cons b xs) = (b,xs)
viewR :: Uniform.T a b -> (Maybe (Uniform.T a b, a), b)
viewR (Uniform.Cons b0 xs0) =
Disp.switchR
(Nothing, b0)
(\ xs a b -> (Just (consSecond b0 xs, a), b))
xs0
viewFirstR :: Disp.T b a -> Maybe (Uniform.T a b, a)
viewFirstR =
Monad.liftM (\ (xs, ~(a,b)) -> (snocSecond xs a, b)) .
Disp.viewR
{-
TODO:
Must be more lazy in case of
@viewSecondR (2 /. 'a' ./ 3 /. 'b' ./ 4 /. undefined)@.
It must also return the @'b'@ but it does not.
-}
viewSecondR :: Uniform.T a b -> (Disp.T b a, b)
viewSecondR (Uniform.Cons b0 xs0) =
Disp.switchR
(Disp.empty, b0)
(\ xs a b -> (consFirst b0 (snocSecond xs a), b))
xs0
{-# INLINE switchL #-}
switchL :: (b -> c) -> (b -> a -> Uniform.T a b -> c) -> Uniform.T a b -> c
switchL f g =
switchSecondL (\x -> switchFirstL (f x) (g x))
{-# INLINE switchFirstL #-}
switchFirstL :: c -> (a -> Uniform.T a b -> c) -> Disp.T a b -> c
switchFirstL f g =
Disp.switchL f (\ a b xs -> g a (consSecond b xs))
{-# INLINE switchSecondL #-}
switchSecondL :: (b -> Disp.T a b -> c) -> Uniform.T a b -> c
switchSecondL f (Uniform.Cons b xs) = f b xs
{-# INLINE switchR #-}
switchR :: (b -> c) -> (Uniform.T a b -> a -> b -> c) -> Uniform.T a b -> c
switchR f g =
switchSecondR (\xs b -> switchFirstR (f b) (\ys a -> g ys a b) xs)
{-# INLINE switchFirstR #-}
switchFirstR :: c -> (Uniform.T a b -> a -> c) -> Disp.T b a -> c
switchFirstR f g =
maybe f (uncurry g) . viewFirstR
{-# INLINE switchSecondR #-}
switchSecondR :: (Disp.T b a -> b -> c) -> Uniform.T a b -> c
switchSecondR f = uncurry f . viewSecondR
-- could also be in ListDisparate
mapFirstL ::
(a -> a, Uniform.T a b0 -> Uniform.T a b1) ->
Disp.T a b0 -> Disp.T a b1
mapFirstL f =
maybe Disp.empty (uncurry consFirst . mapPair f) . viewFirstL
mapFirstHead ::
(a -> a) ->
Disp.T a b -> Disp.T a b
mapFirstHead f = mapFirstL (f,id)
mapFirstTail ::
(Uniform.T a b0 -> Uniform.T a b1) ->
Disp.T a b0 -> Disp.T a b1
mapFirstTail f = mapFirstL (id,f)
mapSecondL ::
(b -> b, Disp.T a0 b -> Disp.T a1 b) ->
Uniform.T a0 b -> Uniform.T a1 b
mapSecondL f = uncurry consSecond . mapPair f . viewSecondL
{-
mapSecondHead ::
(b -> b) ->
Uniform.T a b -> Uniform.T a b
mapSecondHead f = mapSecondL (f,id)
-}
mapSecondTail ::
(Disp.T a0 b -> Disp.T a1 b) ->
Uniform.T a0 b -> Uniform.T a1 b
mapSecondTail f = mapSecondL (id,f)
mapFirstR ::
(Uniform.T a b0 -> Uniform.T a b1, a -> a) ->
Disp.T b0 a -> Disp.T b1 a
mapFirstR f =
maybe Disp.empty (uncurry snocFirst . mapPair f) . viewFirstR
-- could also be in ListDisparate
mapFirstLast ::
(a -> a) ->
Disp.T b a -> Disp.T b a
mapFirstLast f = mapFirstR (id,f)
mapFirstInit ::
(Uniform.T a b0 -> Uniform.T a b1) ->
Disp.T b0 a -> Disp.T b1 a
mapFirstInit f = mapFirstR (f,id)
mapSecondR ::
(Disp.T b a0 -> Disp.T b a1, b -> b) ->
Uniform.T a0 b -> Uniform.T a1 b
mapSecondR f = uncurry snocSecond . mapPair f . viewSecondR
mapSecondLast ::
(b -> b) ->
Uniform.T a b -> Uniform.T a b
mapSecondLast f = mapSecondR (id,f)
mapSecondInit ::
(Disp.T b a0 -> Disp.T b a1) ->
Uniform.T a0 b -> Uniform.T a1 b
mapSecondInit f = mapSecondR (f,id)
appendUniformUniform :: Uniform.T a b -> Uniform.T b a -> Disp.T b a
appendUniformUniform xs ys =
Uniform.foldr consSecond consFirst ys xs
appendDisparateUniform :: Disp.T b a -> Uniform.T a b -> Uniform.T a b
appendDisparateUniform xs ys =
Disp.foldr consSecond consFirst ys xs
appendUniformDisparate :: Uniform.T a b -> Disp.T a b -> Uniform.T a b
appendUniformDisparate xs ys =
mapSecondTail (flip Disp.append ys) xs
concatDisparate :: Disp.T (Uniform.T b a) (Uniform.T a b) -> Disp.T a b
concatDisparate =
Disp.foldr appendUniformUniform appendUniformDisparate Disp.empty
concatUniform :: Uniform.T (Uniform.T b a) (Uniform.T a b) -> Uniform.T a b
concatUniform =
switchSecondL
(\ b xs -> appendUniformDisparate b (concatDisparate xs))
splitAtDisparateUniform :: Int -> Uniform.T a b -> (Disp.T b a, Uniform.T a b)
splitAtDisparateUniform 0 = (,) Disp.empty
splitAtDisparateUniform n =
(\ ~(prefix,suffix) ->
maybe
(error "splitAtDisparateUniform: empty list")
(mapFst (snocFirst prefix))
(viewFirstL suffix)) .
splitAtUniformDisparate (pred n)
splitAtUniformDisparate :: Int -> Uniform.T a b -> (Uniform.T a b, Disp.T a b)
splitAtUniformDisparate n (Uniform.Cons b xs) =
mapFst (consSecond b) $ Disp.splitAt n xs
splitAtUniformUniform ::
Int -> Disp.T b a -> Maybe (Uniform.T a b, Uniform.T b a)
splitAtUniformUniform n =
(\ ~(xs,ys) ->
fmap
(mapFst (snocSecond xs))
(viewFirstL ys)) .
Disp.splitAt n
takeDisparate :: Int -> Uniform.T a b -> Disp.T b a
takeDisparate n =
fst . viewSecondR . takeUniform n
takeUniform :: Int -> Uniform.T a b -> Uniform.T a b
takeUniform n (Uniform.Cons b xs) =
consSecond b $ Disp.take n xs
dropDisparate :: Int -> Uniform.T a b -> Disp.T a b
dropDisparate n = Disp.drop n . snd . viewSecondL
dropUniform :: Int -> Uniform.T a b -> Uniform.T a b
dropUniform 0 = id
dropUniform n =
switchFirstL (error "dropUniform: empty list") (flip const) .
dropDisparate (pred n)
{-
breakDisparateFirst :: (a -> Bool) ->
Disp.T a b -> (Disp.T a b, Disp.T a b)
breakDisparateFirst p = Disp.spanFirst (not . p)
breakUniformFirst :: (a -> Bool) ->
Uniform.T a b -> (Uniform.T a b, Disp.T a b)
breakUniformFirst p =
let recourse xs0 =
(\(b,xs) ->
if p b
then (empty, xs0)
else
maybe
(\(a,ys) ->)
let (as,) = recourse xs
in ) $
viewSecondL xs0
-}
{-
spanSecond :: (b -> Bool) -> Uniform.T a b -> (Uniform.T a b, Disp.T b a)
spanSecond p (Uniform.Cons b xs) =
mapFst (consSecond b) (Disp.span p xs)
spanDisparate :: (b -> Bool) -> Disp.T a b -> (Uniform.T b a, Uniform.T a b)
spanDisparate p =
mapPair (consSecond, consSecond) . List.span (p . pairFirst) . toPairList
-}