module Wumpus.Core.Utils.JoinList
(
JoinList
, ViewL(..)
, fromList
, toList
, toListF
, one
, cons
, snoc
, join
, head
, accumMapL
, isOne
, isMany
, viewl
) where
import Control.Applicative hiding ( empty )
import Data.Foldable ( Foldable )
import qualified Data.Foldable as F
import Data.Monoid ( mappend )
import Data.Traversable ( Traversable(..) )
import Prelude hiding ( head )
data JoinList a = One a
| Join (JoinList a) (JoinList a)
deriving (Eq)
data ViewL a = OneL a | a :< (JoinList a)
deriving (Eq,Show)
instance Show a => Show (JoinList a) where
showsPrec _ xs = showString "fromList " . shows (toList xs)
instance Functor JoinList where
fmap f (One a) = One (f a)
fmap f (Join t u) = Join (fmap f t) (fmap f u)
instance Foldable JoinList where
foldMap f (One a) = f a
foldMap f (Join t u) = F.foldMap f t `mappend` F.foldMap f u
foldr = joinfoldr
foldl = joinfoldl
instance Traversable JoinList where
traverse f (One a) = One <$> f a
traverse f (Join t u) = Join <$> traverse f t <*> traverse f u
instance Functor ViewL where
fmap f (OneL a) = OneL $ f a
fmap f (a :< as) = f a :< fmap f as
toList :: JoinList a -> [a]
toList = joinfoldl (flip (:)) []
fromList :: [a] -> JoinList a
fromList [] = error "Wumpus.Core - internal error empty JoinList"
fromList [x] = One x
fromList (x:xs) = Join (One x) (fromList xs)
toListF :: (a -> b) -> JoinList a -> [b]
toListF f = step []
where
step acc (One x) = f x : acc
step acc (Join t u) = let acc' = step acc u in step acc' t
isOne :: JoinList a -> Bool
isOne (One _) = True
isOne _ = False
isMany :: JoinList a -> Bool
isMany (Join _ _) = True
isMany _ = False
one :: a -> JoinList a
one = One
cons :: a -> JoinList a -> JoinList a
cons a xs = Join (One a) xs
snoc :: JoinList a -> a -> JoinList a
snoc xs a = Join xs (One a)
infixr 5 `join`
join :: JoinList a -> JoinList a -> JoinList a
join = Join
head :: JoinList a -> a
head (One a) = a
head (Join t _) = head t
accumMapL :: (x -> st -> (y,st)) -> JoinList x -> st -> (JoinList y,st)
accumMapL f xs st0 = go xs st0
where
go (One x) st = let (y,st') = f x st in (One y,st')
go (Join t u) st = (Join v w, st'')
where (v,st') = go t st
(w,st'') = go u st'
joinfoldr :: (a -> b -> b) -> b -> JoinList a -> b
joinfoldr f = go
where
go e (One a) = f a e
go e (Join t u) = go (go e t) u
joinfoldl :: (b -> a -> b) -> b -> JoinList a -> b
joinfoldl f = go
where
go e (One a) = f e a
go e (Join t u) = go (go e u) t
viewl :: JoinList a -> ViewL a
viewl (One a) = OneL a
viewl (Join t u) = step t u
where
step (One a) r = a :< r
step (Join t' u') r = step t' (Join u' r)