{-# LANGUAGE CPP #-}
-- | Non-empty random access list.
--
-- This module is designed to imported qualifed.
--
module Data.RAList.NonEmpty (
    NERAList (..),
    NERAList' (..),
    -- * Showing
    explicitShow,
    explicitShowsPrec,
    -- * Construction
    singleton,
    cons,
    -- * Indexing
    (!),
    (!?),
    head,
    last,
    uncons,
    tail,
    length,
    null,
    -- * Conversions
    toNonEmpty,
    fromNonEmpty,
    -- * Folding
    foldMap1,
    foldr1Map,
    ifoldMap,
    ifoldMap1,
    ifoldr1Map,
    -- * Mapping
    adjust,
    map,
    imap,
    itraverse,
#ifdef MIN_VERSION_semigroupoids
    itraverse1,
#endif
    ) where

import Prelude (snd)
import Data.RAList.NonEmpty.Internal

import Data.RAList.Tree (Leaf (..), Node (..))
import Data.RAList.Internal (RAList (..))

-- $setup
-- >>> import Prelude (($))
-- >>> import Data.List.NonEmpty (NonEmpty (..))

-------------------------------------------------------------------------------
-- Extras
-------------------------------------------------------------------------------

-- | Tail of non-empty list can be empty.
--
-- >>> tail $ fromNonEmpty $ 'a' :| "bcdef"
-- fromList "bcdef"
--
tail :: NERAList a -> RAList a
tail :: NERAList a -> RAList a
tail NERAList a
r = (a, RAList a) -> RAList a
forall a b. (a, b) -> b
snd (NERAList a -> (a, RAList a)
forall a. NERAList a -> (a, RAList a)
uncons NERAList a
r)

-- | 
-- >>> uncons $ fromNonEmpty $ 'a' :| "bcdef"
-- ('a',fromList "bcdef")
uncons :: NERAList a -> (a, RAList a)
uncons :: NERAList a -> (a, RAList a)
uncons (NE (Last  (Lf a
x)))   = (a
x, RAList a
forall a. RAList a
Empty)
uncons (NE (Cons1 (Lf a
x) NERAList' (Node Leaf) a
r)) = (a
x, NERAList a -> RAList a
forall a. NERAList a -> RAList a
NonEmpty (NERAList' Leaf a -> NERAList a
forall a. NERAList' Leaf a -> NERAList a
NE (NERAList' (Node Leaf) a -> NERAList' Leaf a
forall (f :: * -> *) a. NERAList' (Node f) a -> NERAList' f a
Cons0 NERAList' (Node Leaf) a
r)))
uncons (NE (Cons0        NERAList' (Node Leaf) a
r)) = 
    let (Lf a
x, NERAList' Leaf a
r') = NERAList' (Node Leaf) a -> (Leaf a, NERAList' Leaf a)
forall (t :: * -> *) a.
NERAList' (Node t) a -> (t a, NERAList' t a)
unconsTree NERAList' (Node Leaf) a
r in (a
x, NERAList a -> RAList a
forall a. NERAList a -> RAList a
NonEmpty (NERAList' Leaf a -> NERAList a
forall a. NERAList' Leaf a -> NERAList a
NE NERAList' Leaf a
r'))

unconsTree :: NERAList' (Node t) a -> (t a, NERAList' t a)
unconsTree :: NERAList' (Node t) a -> (t a, NERAList' t a)
unconsTree (Last  (Nd t a
x t a
y))   = (t a
x, t a -> NERAList' t a
forall (f :: * -> *) a. f a -> NERAList' f a
Last t a
y)
unconsTree (Cons1 (Nd t a
x t a
y) NERAList' (Node (Node t)) a
r) = (t a
x, t a -> NERAList' (Node t) a -> NERAList' t a
forall (f :: * -> *) a.
f a -> NERAList' (Node f) a -> NERAList' f a
Cons1 t a
y (NERAList' (Node (Node t)) a -> NERAList' (Node t) a
forall (f :: * -> *) a. NERAList' (Node f) a -> NERAList' f a
Cons0 NERAList' (Node (Node t)) a
r))
unconsTree (Cons0          NERAList' (Node (Node t)) a
r) = 
    let (Nd t a
x t a
y, NERAList' (Node t) a
r') = NERAList' (Node (Node t)) a -> (Node t a, NERAList' (Node t) a)
forall (t :: * -> *) a.
NERAList' (Node t) a -> (t a, NERAList' t a)
unconsTree NERAList' (Node (Node t)) a
r in (t a
x, t a -> NERAList' (Node t) a -> NERAList' t a
forall (f :: * -> *) a.
f a -> NERAList' (Node f) a -> NERAList' f a
Cons1 t a
y NERAList' (Node t) a
r')