module Manatee.Toolkit.Data.ListZipper where
import Data.Maybe
import Manatee.Toolkit.General.List
import qualified Data.List as List
data ListZipper a = ListZipper ![a] ![a]
instance Show a => Show (ListZipper a) where
show (ListZipper ls rs) = show (reverse ls) ++ show rs
instance Functor ListZipper where
fmap f (ListZipper ls rs) = ListZipper (map f ls) (map f rs)
empty :: ListZipper a
empty = ListZipper [] []
singleton :: a -> ListZipper a
singleton a = ListZipper [] [a]
fromList :: [a] -> ListZipper a
fromList = ListZipper []
fromListEnd :: [a] -> ListZipper a
fromListEnd as = ListZipper (reverse as) []
toList :: ListZipper a -> [a]
toList (ListZipper ls rs) = reverse ls ++ rs
atStart :: ListZipper a -> Bool
atStart (ListZipper [] _ ) = True
atStart _ = False
atEnd :: ListZipper a -> Bool
atEnd (ListZipper _ []) = True
atEnd _ = False
isEmpty :: ListZipper a -> Bool
isEmpty (ListZipper [] []) = True
isEmpty _ = False
getCurrent :: ListZipper a -> Maybe a
getCurrent list = get list $ currentIndex list
getLeft :: ListZipper a -> Maybe a
getLeft list = get list $ leftIndex list
getRight :: ListZipper a -> Maybe a
getRight list = get list $ rightIndex list
getFirst :: ListZipper a -> Maybe a
getFirst list = get list $ firstIndex list
getLast :: ListZipper a -> Maybe a
getLast list = get list $ lastIndex list
getLeftCircular :: ListZipper a -> Maybe a
getLeftCircular list
| prevIndex < firstIndex list
= get list $ lastIndex list
| otherwise
= get list prevIndex
where
prevIndex = leftIndex list
getRightCircular :: ListZipper a -> Maybe a
getRightCircular list
| nextIndex > lastIndex list
= get list $ firstIndex list
| otherwise
= get list nextIndex
where
nextIndex = rightIndex list
get :: ListZipper a -> Int -> Maybe a
get = (?!) . toList
focusLeft :: ListZipper a -> Maybe (ListZipper a)
focusLeft (ListZipper (a:ls) rs) = Just $ ListZipper ls (a:rs)
focusLeft _ = Nothing
focusRight :: ListZipper a -> Maybe (ListZipper a)
focusRight (ListZipper ls (a:rs)) = Just $ ListZipper (a:ls) rs
focusRight _ = Nothing
focusFirst :: ListZipper a -> Maybe (ListZipper a)
focusFirst list = focus (firstIndex list) list
focusLast :: ListZipper a -> Maybe (ListZipper a)
focusLast list = focus (lastIndex list) list
focus :: Int -> ListZipper a -> Maybe (ListZipper a)
focus n list
| n < 0
= Nothing
| n >= lenList
= Nothing
| n == currIndex
= Just list
| n < currIndex
= (=<<) (focus n) leftList
| otherwise
= (=<<) (focus n) rightList
where
lenList = Manatee.Toolkit.Data.ListZipper.length list
currIndex = currentIndex list
leftList = focusLeft list
rightList = focusRight list
focusNode :: Eq a => a -> ListZipper a -> Maybe (ListZipper a)
focusNode a list =
(=<<) (`focus` list) index
where
index = List.findIndex (a ==) (toList list)
insertLeft :: a -> ListZipper a -> ListZipper a
insertLeft a (ListZipper ls rs) = ListZipper (a:ls) rs
insertRight :: a -> ListZipper a -> ListZipper a
insertRight a (ListZipper ls (r:rs)) = ListZipper ls (r:a:rs)
insertRight a (ListZipper ls _) = ListZipper ls [a]
insertFirst :: a -> ListZipper a -> ListZipper a
insertFirst a (ListZipper (l:ls) rs) = ListZipper ((l:ls) ++ [a]) rs
insertFirst a (ListZipper _ rs) = ListZipper [a] rs
insertLast :: a -> ListZipper a -> ListZipper a
insertLast a (ListZipper ls (r:rs)) = ListZipper ls ((r:rs) ++ [a])
insertLast a (ListZipper ls _) = ListZipper ls [a]
delete :: ListZipper a -> Maybe (ListZipper a)
delete (ListZipper ls (_:rs)) = Just $ ListZipper ls rs
delete _ = Nothing
deleteLeft :: ListZipper a -> Maybe (ListZipper a)
deleteLeft (ListZipper (_:ls) rs) = Just $ ListZipper ls rs
deleteLeft _ = Nothing
deleteRight :: ListZipper a -> Maybe (ListZipper a)
deleteRight (ListZipper ls (r:_:rs)) = Just $ ListZipper ls (r:rs)
deleteRight _ = Nothing
deleteFirst :: ListZipper a -> Maybe (ListZipper a)
deleteFirst (ListZipper (l:ls) rs) = Just $ ListZipper (init (l:ls)) rs
deleteFirst (ListZipper [] (_:rs)) = Just $ ListZipper [] rs
deleteFirst _ = Nothing
deleteLast :: ListZipper a -> Maybe (ListZipper a)
deleteLast (ListZipper ls (r:rs)) = Just $ ListZipper ls (init (r:rs))
deleteLast (ListZipper (_:ls) rs) = Just $ ListZipper ls rs
deleteLast _ = Nothing
deleteOthers :: ListZipper a -> Maybe (ListZipper a)
deleteOthers (ListZipper _ (r:_)) = Just $ ListZipper [] [r]
deleteOthers _ = Nothing
deleteNode :: Eq a => a -> ListZipper a -> Maybe (ListZipper a)
deleteNode a (ListZipper ls rs)
| isJust leftIndex
= Just $ ListZipper (deleteAt (fromJust leftIndex) ls) rs
| isJust rightIndex
= Just $ ListZipper ls (deleteAt (fromJust rightIndex) rs)
| otherwise
= Nothing
where
leftIndex = List.findIndex (a ==) ls
rightIndex = List.findIndex (a ==) rs
swapLeft :: ListZipper a -> Maybe (ListZipper a)
swapLeft (ListZipper (l:ls) (r:rs)) = Just $ ListZipper (r:ls) (l:rs)
swapLeft (ListZipper (l:ls) _) = Just $ ListZipper ls [l]
swapLeft _ = Nothing
swapRight :: ListZipper a -> Maybe (ListZipper a)
swapRight (ListZipper ls (r:x:rs)) = Just $ ListZipper ls (x:r:rs)
swapRight _ = Nothing
replace :: a -> ListZipper a -> Maybe (ListZipper a)
replace a (ListZipper ls (_:rs)) = Just $ ListZipper ls (a:rs)
replace _ _ = Nothing
length :: ListZipper a -> Int
length (ListZipper ls rs) = Prelude.length ls + Prelude.length rs
currentIndex :: ListZipper a -> Int
currentIndex (ListZipper ls _) = Prelude.length ls
leftIndex :: ListZipper a -> Int
leftIndex = pred . currentIndex
rightIndex :: ListZipper a -> Int
rightIndex = succ . currentIndex
firstIndex :: ListZipper a -> Int
firstIndex _ = 0
lastIndex :: ListZipper a -> Int
lastIndex = pred . Manatee.Toolkit.Data.ListZipper.length