module Data.JoinList
(
JoinList
, empty
, wrap
, ( ++ )
, join
, null
, concat
, length
, map
, replicate
, repeated
, gfold
, xzip
, xzipWith
, toList
, fromList
) where
import Control.Applicative hiding ( empty )
import Data.Monoid
import Data.Traversable
import Text.Show ( showListWith )
import qualified Data.Foldable as F
import qualified Data.List as L
import Prelude hiding ( (++), null, length, map, concat, replicate )
data JoinList a = Empty
| Single a
| Join (JoinList a) (JoinList a)
deriving (Eq)
instance Show a => Show (JoinList a) where
showsPrec _ xs = showChar '(' . showListWith shows (toList xs) . showChar ')'
instance Monoid (JoinList a) where
mempty = Empty
mappend = (++)
instance Functor JoinList where
fmap _ Empty = Empty
fmap f (Single a) = Single (f a)
fmap f (Join a b) = (fmap f a) ++ (fmap f b)
instance Monad JoinList where
return = Single
Empty >>= _ = Empty
Single a >>= k = k a
Join t u >>= k = Join (concat $ fmap k t) (concat $ fmap k u)
instance F.Foldable JoinList where
foldMap _ Empty = mempty
foldMap f (Single a) = f a
foldMap f (Join t u) = F.foldMap f t `mappend` F.foldMap f u
instance Traversable JoinList where
traverse _ Empty = pure Empty
traverse f (Single a) = Single <$> f a
traverse f (Join t u) = Join <$> traverse f t <*> traverse f u
empty :: JoinList a
empty = Empty
wrap :: a -> JoinList a
wrap = Single
infixr 5 ++
(++) :: JoinList a -> JoinList a -> JoinList a
Empty ++ ys = ys
xs ++ Empty = xs
xs ++ ys = Join xs ys
infixr 5 `join`
join :: JoinList a -> JoinList a -> JoinList a
join = (++)
null :: JoinList a -> Bool
null Empty = True
null _ = False
concat :: JoinList (JoinList a) -> JoinList a
concat = F.foldl' mappend mempty
length :: JoinList a -> Int
length = gfold 0 (const 1) (+)
map :: (a -> b) -> JoinList a -> JoinList b
map = fmap
replicate :: Int -> a -> JoinList a
replicate n a | n > 0 = step (n1) (Single a)
| otherwise = Empty
where
step 0 xs = xs
step i xs = step (i1) $ Single a `Join` xs
repeated :: Int -> JoinList a -> JoinList a
repeated n xs | n > 0 = step (n1) xs
| otherwise = Empty
where
step 0 ys = ys
step i ys = step (i1) $ xs `Join` ys
gfold :: b
-> (a -> b)
-> (b -> b -> b)
-> JoinList a
-> b
gfold e _ _ Empty = e
gfold _ f _ (Single a) = f a
gfold e f g (Join t u) = g (gfold e f g t) (gfold e f g u)
xzip :: JoinList a -> [b] -> JoinList (a,b)
xzip = xzipWith (,)
xzipWith :: (a -> b -> c) -> JoinList a -> [b] -> JoinList c
xzipWith fn xs0 ys0 = fst $ step xs0 ys0
where
step Empty xs = (Empty,xs)
step (Single a) (x:xs) = (Single (fn a x),xs)
step (Single _) [] = (Empty,[])
step (Join t u) xs = (Join t' u',xs'') where
(t',xs') = step t xs
(u',xs'') = step u xs'
toList :: JoinList a -> [a]
toList = F.foldr (:) []
fromList :: [a] -> JoinList a
fromList [] = Empty
fromList (x:xs) = L.foldl' (\a e -> a `Join` (Single e)) (Single x) xs