{-# LANGUAGE CPP #-}
module Acc.NeAcc.Def
(
NeAcc(..),
foldM,
fromList1,
uncons,
unconsTo,
unsnoc,
unsnocTo,
appendEnumFromTo,
)
where
import Acc.Prelude hiding (foldM)
import qualified Acc.Prelude as Prelude
data NeAcc a =
Leaf !a |
Branch !(NeAcc a) !(NeAcc a)
deriving (Generic, Generic1)
instance Show a => Show (NeAcc a) where
show =
show . toList
instance NFData a => NFData (NeAcc a)
instance NFData1 NeAcc
instance IsList (NeAcc a) where
type Item (NeAcc a) = a
fromList =
\ case
a : b -> fromList1 a b
_ -> error "Empty input list"
toList =
foldr (:) []
deriving instance Functor NeAcc
instance Applicative NeAcc where
pure =
Leaf
(<*>) =
\ case
Branch a b ->
\ c ->
Branch (a <*> c) (b <*> c)
Leaf a ->
fmap a
instance Foldable NeAcc where
foldr :: (a -> b -> b) -> b -> NeAcc a -> b
foldr step acc =
peel []
where
peel layers =
\ case
Leaf a ->
step a (unpeel layers)
Branch l r ->
peel (r : layers) l
unpeel =
\ case
h : t ->
peel t h
_ ->
acc
foldr' :: (a -> b -> b) -> b -> NeAcc a -> b
foldr' step =
peel []
where
peel layers acc =
\ case
Leaf a ->
unpeel (step a acc) layers
Branch l r ->
peel (l : layers) acc r
unpeel !acc =
\ case
h : t ->
peel t acc h
_ ->
acc
foldl :: (b -> a -> b) -> b -> NeAcc a -> b
foldl step acc =
\ case
Branch a b ->
foldlOnBranch step acc a b
Leaf a ->
step acc a
where
foldlOnBranch :: (b -> a -> b) -> b -> NeAcc a -> NeAcc a -> b
foldlOnBranch step acc a b =
case b of
Leaf c ->
step (foldl step acc a) c
Branch c d ->
foldlOnBranch step acc (Branch a c) d
foldl' :: (b -> a -> b) -> b -> NeAcc a -> b
foldl' step !acc =
\ case
Branch a b ->
foldlOnBranch' step acc a b
Leaf a ->
step acc a
where
foldlOnBranch' :: (b -> a -> b) -> b -> NeAcc a -> NeAcc a -> b
foldlOnBranch' step acc a b =
case a of
Leaf c ->
foldl' step (step acc c) b
Branch c d ->
foldlOnBranch' step acc c (Branch d b)
foldMap :: Monoid m => (a -> m) -> NeAcc a -> m
foldMap =
foldMapTo mempty
where
foldMapTo :: Monoid m => m -> (a -> m) -> NeAcc a -> m
foldMapTo acc map =
\ case
Branch a b -> foldMapToOnBranch acc map a b
Leaf a -> acc <> map a
foldMapToOnBranch :: Monoid m => m -> (a -> m) -> NeAcc a -> NeAcc a -> m
foldMapToOnBranch acc map a b =
case a of
Leaf c -> foldMapTo (acc <> map c) map b
Branch c d -> foldMapToOnBranch acc map c (Branch d b)
#if MIN_VERSION_base(4,13,0)
foldMap' :: Monoid m => (a -> m) -> NeAcc a -> m
foldMap' =
foldMapTo' mempty
where
foldMapTo' :: Monoid m => m -> (a -> m) -> NeAcc a -> m
foldMapTo' !acc map =
\ case
Branch a b -> foldMapToOnBranch' acc map a b
Leaf a -> acc <> map a
foldMapToOnBranch' :: Monoid m => m -> (a -> m) -> NeAcc a -> NeAcc a -> m
foldMapToOnBranch' acc map a b =
case a of
Leaf c -> foldMapTo' (acc <> map c) map b
Branch c d -> foldMapToOnBranch' acc map c (Branch d b)
#endif
instance Traversable NeAcc where
traverse :: Applicative f => (a -> f b) -> NeAcc a -> f (NeAcc b)
traverse map =
\ case
Branch a b ->
traverseOnBranch map a b
Leaf a ->
Leaf <$> map a
where
traverseOnBranch :: Applicative f => (a -> f b) -> NeAcc a -> NeAcc a -> f (NeAcc b)
traverseOnBranch map a b =
case a of
Leaf c ->
Branch <$> Leaf <$> map c <*> traverse map b
Branch c d ->
traverseOnBranch map a (Branch d b)
instance Foldable1 NeAcc where
fold1 :: Semigroup m => NeAcc m -> m
fold1 =
\ case
Branch l r ->
rebalancingLeft l r (foldl' (<>))
Leaf a ->
a
foldMap1 :: Semigroup m => (a -> m) -> NeAcc a -> m
foldMap1 f =
\ case
Branch l r ->
rebalancingLeft l r (foldl' (\ m a -> m <> f a) . f)
Leaf a ->
f a
toNonEmpty :: NeAcc a -> NonEmpty a
toNonEmpty =
findFirst
where
findFirst =
\ case
Branch l r ->
findFirstOnBranch l r
Leaf a ->
a :| []
findFirstOnBranch l r =
case l of
Branch ll lr ->
findFirstOnBranch ll (Branch lr r)
Leaf a ->
a :| foldr (:) [] r
instance Traversable1 NeAcc where
traverse1 map =
\ case
Branch a b ->
traverseOnBranch map a b
Leaf a ->
Leaf <$> map a
where
traverseOnBranch map a b =
case a of
Leaf c ->
Branch <$> Leaf <$> map c <.> traverse1 map b
Branch c d ->
traverseOnBranch map a (Branch d b)
instance Alt NeAcc where
(<!>) =
Branch
instance Semigroup (NeAcc a) where
(<>) =
Branch
rebalancingLeft :: NeAcc a -> NeAcc a -> (a -> NeAcc a -> b) -> b
rebalancingLeft l r cont =
case l of
Branch ll lr ->
rebalancingLeft ll (Branch lr r) cont
Leaf a ->
cont a r
foldM :: Monad m => (a -> b -> m a) -> a -> NeAcc b -> m a
foldM step !acc =
\ case
Branch a b -> foldMOnBranch step acc a b
Leaf a -> step acc a
where
foldMOnBranch :: Monad m => (a -> b -> m a) -> a -> NeAcc b -> NeAcc b -> m a
foldMOnBranch step acc a b =
case a of
Leaf c -> step acc c >>= \ acc' -> foldM step acc' b
Branch c d -> foldMOnBranch step acc c (Branch d b)
fromList1 :: a -> [a] -> NeAcc a
fromList1 a =
\ case
b : c -> fromList1To (Leaf a) b c
_ -> Leaf a
fromList1To :: NeAcc a -> a -> [a] -> NeAcc a
fromList1To leftTree a =
\ case
b : c -> fromList1To (Branch leftTree (Leaf a)) b c
_ -> Branch leftTree (Leaf a)
uncons :: NeAcc a -> (a, Maybe (NeAcc a))
uncons =
\ case
Branch l r ->
fmap Just (unconsTo r l)
Leaf a ->
(a, Nothing)
unconsTo :: NeAcc a -> NeAcc a -> (a, NeAcc a)
unconsTo buff =
\ case
Branch l r ->
unconsTo (Branch r buff) l
Leaf a ->
(a, buff)
unsnoc :: NeAcc a -> (a, Maybe (NeAcc a))
unsnoc =
\ case
Branch l r ->
fmap Just (unsnocTo l r)
Leaf a ->
(a, Nothing)
unsnocTo :: NeAcc a -> NeAcc a -> (a, NeAcc a)
unsnocTo buff =
\ case
Branch l r ->
unsnocTo (Branch l buff) r
Leaf a ->
(a, buff)
appendEnumFromTo :: (Enum a, Ord a) => a -> a -> NeAcc a -> NeAcc a
appendEnumFromTo from to =
if from <= to
then
appendEnumFromTo (succ from) to . flip Branch (Leaf from)
else
id