{-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE TypeFamilies #-} module Data.ListZipper( -- * data types ListZipper(..) , ListZipperOp(..) , ListZipperOp' -- * lenses and prisms , AsListZipper(..) , HasListZipper(..) , HasListZipperOp(..) , AsListZipperOp(..) -- * traversals , leftz' , rightz' , leftzrightz , rightzleftz -- * make zippers , zipper , zipper0L , zipper0L' , zipper0R , zipper0R' -- * rezip , list -- * indices , zipperIndices -- * transform , rev -- * movement , moveLeft , moveRight , moveStart , moveEnd , moveLeftLoop , moveRightLoop , opWith , moveLeftWith , moveRightWith , moveLeftRightWith , moveRightLeftWith , opWithThen , moveLeftWithThen , moveRightWithThen , moveLeftRightWithThen , moveRightLeftWithThen , opUntil , moveLeftUntil , moveRightUntil , moveLeftRightUntil , moveRightLeftUntil , opUntilThen , moveLeftUntilThen , moveRightUntilThen , moveLeftRightUntilThen , moveRightLeftUntilThen -- * insertion , insertMoveLeft , insertMoveRight -- * deletion , deleteStepLeft , deleteStepRight -- * modifcation , modifyFocus , setFocus -- * focus position , atStart , atEnd -- * get context , getFocus , getLeft , getRight , getRightz , getLeftz , getList -- * list zipper state operations , liftListZipperOp , mkListZipperOp , (<$~) , (*>>) , (<<*) , mkListZipperOp' , (.>>) , (<<.) , runListZipperOp , execListZipperOp , (##>) , (<##) , evalListZipperOp , (&&>) , (<&&) , execOpList , (%%>) , (<%%) , execOpList' , ($$>) , (<$$) , opWhileJust ) where import Control.Applicative(Applicative(pure, (<*>)), Alternative((<|>), empty), (<*)) import Control.Category((.), id) import Control.Comonad(Comonad(duplicate, extract)) import Control.Lens(Each(each), Reversing(reversing), Ixed(ix), Rewrapped, Wrapped(Unwrapped, _Wrapped'), IxValue, Index, Prism', Lens', Traversal', _Wrapped, (^.), iso, (&), _1, _2) import Control.Monad.Error.Class(MonadError(throwError, catchError)) import Control.Monad.Fail(MonadFail(fail)) import Control.Monad.Fix(MonadFix(mfix)) import Control.Monad.Reader(MonadReader(ask, local, reader)) import Control.Monad.State(MonadState(get, put, state)) import qualified Control.Monad.Fail as Fail(fail) import Data.Traversable(Traversable(traverse)) import Data.Semigroup.Traversable(Traversable1(traverse1)) import Control.Monad(Monad((>>=), return), MonadPlus(mplus, mzero), (=<<)) import Data.Bool(Bool) import Data.Eq(Eq((==))) import Data.Eq.Deriving(deriveEq1) import Data.Foldable(Foldable(toList, foldMap)) import Data.Function(flip) import Data.Functor(Functor(fmap), (<$>), (<$)) import Data.Functor.Alt(Alt(())) import Data.Functor.Apply(Apply((<.>))) import Data.Functor.Bind(Bind((>>-))) import Data.Functor.Extend(Extend(duplicated)) import Data.Int(Int) import Data.List(unfoldr, zipWith, repeat, reverse, null, zip) import Data.List.NonEmpty(NonEmpty((:|))) import Data.Maybe(Maybe(Nothing, Just), fromMaybe) import Data.Monoid(Monoid(mappend, mempty)) import Data.Ord(Ord((<))) import Data.Semigroup(Semigroup((<>))) import Data.Semigroup.Foldable(Foldable1(foldMap1)) import Prelude(Show, (+)) import Text.Show.Deriving(deriveShow1) data ListZipper a = ListZipper [a] a [a] deriving (Eq, Ord, Show) instance Functor ListZipper where fmap f (ListZipper l x r) = ListZipper (fmap f l) (f x) (fmap f r) instance Apply ListZipper where ListZipper l1 x1 r1 <.> ListZipper l2 x2 r2 = ListZipper (zipWith id l1 l2) (x1 x2) (zipWith id r1 r2) instance Applicative ListZipper where pure a = ListZipper (repeat a) a (repeat a) (<*>) = (<.>) instance Foldable ListZipper where foldMap f (ListZipper l x r) = foldMap f l `mappend` f x `mappend` foldMap f r instance Foldable1 ListZipper where foldMap1 f (ListZipper [] x []) = f x foldMap1 f (ListZipper [] x (rh:rt)) = f x <> foldMap1 f (rh :| rt) foldMap1 f (ListZipper (lh:lt) x []) = foldMap1 f (lh :| lt) <> f x foldMap1 f (ListZipper (lh:lt) x (rh:rt)) = foldMap1 f (lh :| lt) <> f x <> foldMap1 f (rh :| rt) instance Traversable ListZipper where traverse f (ListZipper l x r) = ListZipper <$> traverse f l <*> f x <*> traverse f r instance Traversable1 ListZipper where traverse1 f (ListZipper [] x []) = (\x' -> ListZipper [] x' []) <$> f x traverse1 f (ListZipper (lh:lt) x []) = (\l' x' -> ListZipper (toList l') x' []) <$> traverse1 f (lh :| lt) <.> f x traverse1 f (ListZipper [] x (rh:rt)) = (\x' r' -> ListZipper [] x' (toList r')) <$> f x <.> traverse1 f (rh :| rt) traverse1 f (ListZipper (lh:lt) x (rh:rt)) = (\l' x' r' -> ListZipper (toList l') x' (toList r')) <$> traverse1 f (lh :| lt) <.> f x <.> traverse1 f (rh :| rt) instance Semigroup a => Semigroup (ListZipper a) where ListZipper l1 x1 r1 <> ListZipper l2 x2 r2 = ListZipper (zipWith (<>) l1 l2) (x1 <> x2) (zipWith (<>) r1 r2) instance Each (ListZipper a) (ListZipper a) a a where each = traverse instance Reversing (ListZipper a) where reversing (ListZipper l x r) = ListZipper (reverse l) x (reverse r) type instance IxValue (ListZipper a) = a type instance Index (ListZipper a) = Int instance Ixed (ListZipper a) where ix i f z = if i < 0 then pure z else let ListZipper l x r = zipperIndices z applyn (n, a) = if i == n then f a else pure a in ListZipper <$> traverse applyn l <*> applyn x <*> traverse applyn r instance Extend ListZipper where duplicated z = let dup x = (x, x) unf m = unfoldr (fmap dup . (execListZipperOp m)) z in ListZipper (unf moveLeft) z (unf moveRight) instance Comonad ListZipper where duplicate = duplicated extract (ListZipper _ x _) = x class AsListZipper z a | z -> a where _ListZipper :: Prism' z (ListZipper a) instance AsListZipper (ListZipper a) a where _ListZipper = id class HasListZipper z a | z -> a where listZipper :: Lens' z (ListZipper a) focus :: Lens' z a {-# INLINE focus #-} leftz :: Lens' z [a] {-# INLINE leftz #-} rightz :: Lens' z [a] {-# INLINE rightz #-} leftz = listZipper . leftz focus = listZipper . focus rightz = listZipper . rightz instance HasListZipper (ListZipper a) a where {-# INLINE focus #-} {-# INLINE leftz #-} {-# INLINE rightz #-} listZipper = id leftz f (ListZipper l x r) = fmap (\l' -> ListZipper l' x r) (f l) focus f (ListZipper l x r) = fmap (\x' -> ListZipper l x' r) (f x) rightz f (ListZipper l x r) = fmap (\r' -> ListZipper l x r') (f r) leftz' :: HasListZipper z a => Traversal' z a leftz' = leftz . traverse rightz' :: HasListZipper z a => Traversal' z a rightz' = rightz . traverse leftzrightz :: Traversal' (ListZipper a) a leftzrightz f (ListZipper l x r) = (\l' r' -> ListZipper l' x r') <$> traverse f l <*> traverse f r rightzleftz :: Traversal' (ListZipper a) a rightzleftz f (ListZipper l x r) = (\r' l' -> ListZipper l' x r') <$> traverse f r <*> traverse f l zipper :: [a] -> Maybe (ListZipper a) zipper [] = Nothing zipper (h:t) = Just (ListZipper [] h t) zipper0L :: a -> [a] -> ListZipper a zipper0L = ListZipper [] zipper0L' :: NonEmpty a -> ListZipper a zipper0L' (h :| t) = zipper0L h t zipper0R :: [a] -> a -> ListZipper a zipper0R l x = ListZipper l x [] zipper0R' :: NonEmpty a -> ListZipper a zipper0R' (h :| []) = ListZipper [] h [] zipper0R' (h :| i : t) = let ListZipper l x r = zipper0R' (i :| t) in ListZipper (h:l) x r list :: ListZipper a -> [a] list (ListZipper l x r) = reverse l <> (x : r) zipperIndices :: ListZipper a -> ListZipper (Int, a) zipperIndices (ListZipper l x r) = let zipl :: [a] -> [b] -> ([a], [(a, b)]) zipl y [] = (y, []) zipl [] (_:_) = ([], []) zipl (a:b) (c:d) = fmap ((a, c) :) (zipl b d) rl = reverse l (z, l') = zipl [0..] rl ln = case z of n:_ -> n [] -> 0 in ListZipper (reverse l') (ln, x) (zip [ln + 1..] r) rev :: ListZipper a -> ListZipper a rev (ListZipper l x r) = ListZipper r x l moveStart :: ListZipper a -> ListZipper a moveStart = opWhileJust moveLeft moveEnd :: ListZipper a -> ListZipper a moveEnd z = opWhileJust moveRight z atStart :: HasListZipper z a => z -> Bool atStart z = null (z ^. leftz) atEnd :: HasListZipper z a => z -> Bool atEnd z = null (z ^. rightz) moveLeftLoop :: ListZipper a -> ListZipper a moveLeftLoop z = fromMaybe (moveEnd z) (execListZipperOp moveLeft z) moveRightLoop :: ListZipper a -> ListZipper a moveRightLoop z = fromMaybe (moveStart z) (execListZipperOp moveRight z) insertMoveLeft :: a -> ListZipper a -> ListZipper a insertMoveLeft a (ListZipper l x r) = ListZipper (x:l) a r insertMoveRight :: a -> ListZipper a -> ListZipper a insertMoveRight a (ListZipper l x r) = ListZipper l a (x:r) ---- newtype ListZipperOp a b = ListZipperOp (ListZipper a -> Maybe (ListZipper a, b)) type ListZipperOp' a = ListZipperOp a () instance ListZipperOp a x ~ t => Rewrapped (ListZipperOp b' a') t instance Wrapped (ListZipperOp a' x') where type Unwrapped (ListZipperOp a' x') = ListZipper a' -> Maybe (ListZipper a', x') _Wrapped' = iso (\(ListZipperOp k) -> k) ListZipperOp class HasListZipperOp lo x y | lo -> x y where lo :: Lens' lo (ListZipperOp x y) instance HasListZipperOp (ListZipperOp x y) x y where lo = id class AsListZipperOp t x y | t -> x y where _ListZipperOp :: Prism' t (ListZipperOp x y) instance AsListZipperOp (ListZipperOp x y) x y where _ListZipperOp = id instance Functor (ListZipperOp a) where fmap f (ListZipperOp k) = ListZipperOp (fmap (fmap f) . k) instance Apply (ListZipperOp a) where ListZipperOp j <.> ListZipperOp k = ListZipperOp (\z -> j z >>= \(z', f) -> k z' >>= \(z'', a) -> pure (z'', f a) ) instance Applicative (ListZipperOp a) where (<*>) = (<.>) pure a = ListZipperOp (\z -> pure (z, a)) instance Bind (ListZipperOp a) where ListZipperOp j >>- f = ListZipperOp (\z -> j z >>- \(z', a) -> z' & f a ^. _Wrapped ) instance Alt (ListZipperOp a) where ListZipperOp j ListZipperOp k = ListZipperOp (\z -> j z k z) instance Alternative (ListZipperOp x) where (<|>) = () empty = ListZipperOp (pure empty) instance Monad (ListZipperOp a) where (>>=) = (>>-) return = pure instance MonadPlus (ListZipperOp a) where ListZipperOp j `mplus` ListZipperOp k = ListZipperOp (\z -> j z `mplus` k z) mzero = ListZipperOp (pure mzero) instance Semigroup (ListZipperOp a b) where ListZipperOp j <> ListZipperOp k = ListZipperOp (\z -> j z k z) instance Monoid (ListZipperOp a b) where mappend = (<>) mempty = ListZipperOp (pure Nothing) instance MonadState (ListZipper a) (ListZipperOp a) where get = ListZipperOp (\z -> Just (z, z)) put z = ListZipperOp (\_ -> Just (z, ())) state k = ListZipperOp (\z -> let (z', a) = k z in Just (a, z')) instance MonadReader (ListZipper a) (ListZipperOp a) where ask = ListZipperOp (\z -> Just (z, z)) local k (ListZipperOp o) = ListZipperOp (\z -> (\(z', a) -> (k z', a)) <$> o z) reader k = ListZipperOp (\z -> Just (z, k z)) instance MonadFix (ListZipperOp a) where mfix f = ListZipperOp (\z -> mfix (\ ~(_, a) -> z & f a ^. _Wrapped) ) instance MonadFail (ListZipperOp a) where fail s = ListZipperOp (\_ -> Fail.fail s ) instance MonadError () (ListZipperOp a) where throwError () = ListZipperOp (\_ -> Nothing) catchError (ListZipperOp k) f = ListZipperOp (\z -> k z (z & f () ^. _Wrapped) ) liftListZipperOp :: Maybe b -> ListZipperOp a b liftListZipperOp m = ListZipperOp (\z -> (\b -> (z, b)) <$> m ) getFocus :: ListZipperOp a a getFocus = reader (^. focus) getLeft :: ListZipperOp a a getLeft = do z <- get case z of ListZipper (l:_) _ _ -> pure l ListZipper [] _ _ -> mempty getRight :: ListZipperOp a a getRight = do z <- get case z of ListZipper _ _ (r:_) -> pure r ListZipper _ _ [] -> mempty getRightz :: ListZipperOp a [a] getRightz = reader (^. rightz) getLeftz :: ListZipperOp a [a] getLeftz = reader (^. leftz) getList :: ListZipperOp a [a] getList = reader list mkListZipperOp :: (ListZipper a -> Maybe b) -> ListZipperOp a b mkListZipperOp f = get >>= liftListZipperOp . f (<$~) :: ListZipperOp a b -> ListZipperOp a c -> ListZipperOp a b ListZipperOp x <$~ ListZipperOp y = ListZipperOp (\z -> case x z of Nothing -> Nothing Just (z', r) -> fmap (r <$) (y z') ) infixl 5 <$~ (*>>) :: (ListZipper a -> Maybe b) -> ListZipperOp a c -> ListZipperOp a b f *>> k = mkListZipperOp f <* k infixl 5 *>> (<<*) :: ListZipperOp a c -> (ListZipper a -> Maybe b) -> ListZipperOp a b (<<*) = flip (*>>) infixl 5 <<* mkListZipperOp' :: (ListZipper a -> Maybe (ListZipper a)) -> ListZipperOp' a mkListZipperOp' f = ListZipperOp (\s -> (\s' -> (s', ())) <$> f s) (.>>) :: (ListZipper a -> Maybe (ListZipper a)) -> ListZipperOp a b -> ListZipperOp' a f .>> k = mkListZipperOp' f <* k infixl 5 .>> (<<.) :: ListZipperOp a b -> (ListZipper a -> Maybe (ListZipper a)) -> ListZipperOp' a (<<.) = flip (.>>) infixl 5 <<. runListZipperOp :: ListZipperOp a x -> ListZipper a -> Maybe (ListZipper a, x) runListZipperOp (ListZipperOp o) z = o z execListZipperOp :: ListZipperOp a x -> ListZipper a -> Maybe (ListZipper a) execListZipperOp o = fmap (^. _1) . runListZipperOp o (##>) :: ListZipperOp a x -> ListZipper a -> Maybe (ListZipper a) (##>) = execListZipperOp infixl 6 ##> (<##) :: ListZipper a -> ListZipperOp a x -> Maybe (ListZipper a) (<##) = flip (##>) infixl 6 <## evalListZipperOp :: ListZipperOp a x -> ListZipper a -> Maybe x evalListZipperOp o = fmap (^. _2) . runListZipperOp o (&&>) :: ListZipperOp a x -> ListZipper a -> Maybe x (&&>) = evalListZipperOp infixl 6 &&> (<&&) :: ListZipper a -> ListZipperOp a x -> Maybe x (<&&) = flip (&&>) infixl 6 <&& execOpList :: ListZipperOp a x -> ListZipper a -> Maybe [a] execOpList o = fmap list . execListZipperOp o (%%>) :: ListZipperOp a x -> ListZipper a -> Maybe [a] (%%>) = execOpList infixl 5 %%> (<%%) :: ListZipper a -> ListZipperOp a x -> Maybe [a] (<%%) = flip (%%>) infixl 5 <%% execOpList' :: ListZipperOp a x -> ListZipper a -> [a] execOpList' o = fromMaybe [] . execOpList o ($$>) :: ListZipperOp a x -> ListZipper a -> [a] ($$>) = execOpList' infixl 5 $$> (<$$) :: ListZipper a -> ListZipperOp a x -> [a] (<$$) = flip ($$>) infixl 5 <$$ moveLeft :: ListZipperOp' a moveLeft = mkListZipperOp' (\z -> case z of ListZipper [] _ _ -> Nothing ListZipper (h:t) x r -> Just (ListZipper t h (x:r)) ) moveRight :: ListZipperOp' a moveRight = mkListZipperOp' (\z -> case z of ListZipper _ _ [] -> Nothing ListZipper l x (h:t) -> Just (ListZipper (x:l) h t) ) opWith :: ListZipperOp a b -> (a -> Maybe c) -> ListZipperOp a c opWith o p = ListZipperOp (\z -> let go z' = let x = z' ^. focus in case p x of Nothing -> go =<< execListZipperOp o z' Just w -> Just (z', w) in go z ) moveLeftWith :: (a -> Maybe c) -> ListZipperOp a c moveLeftWith = opWith moveLeft moveRightWith :: (a -> Maybe c) -> ListZipperOp a c moveRightWith = opWith moveRight moveLeftRightWith :: (a -> Maybe c) -> ListZipperOp a c moveLeftRightWith p = moveLeftWith p moveRightWith p moveRightLeftWith :: (a -> Maybe c) -> ListZipperOp a c moveRightLeftWith p = moveRightWith p moveLeftWith p opWithThen :: ListZipperOp a b -> (a -> Maybe c) -> ListZipperOp a c opWithThen o p = opWith o p <* o moveLeftWithThen :: (a -> Maybe c) -> ListZipperOp a c moveLeftWithThen = opWithThen moveLeft moveRightWithThen :: (a -> Maybe c) -> ListZipperOp a c moveRightWithThen = opWithThen moveRight moveLeftRightWithThen :: (a -> Maybe c) -> ListZipperOp a c moveLeftRightWithThen p = moveLeftWithThen p moveRightWithThen p moveRightLeftWithThen :: (a -> Maybe c) -> ListZipperOp a c moveRightLeftWithThen p = moveRightWithThen p moveLeftWithThen p opUntil :: ListZipperOp a x -> (a -> Bool) -> ListZipperOp' a opUntil o p = opWith o (\a -> if p a then Just () else Nothing) moveLeftUntil :: (a -> Bool) -> ListZipperOp' a moveLeftUntil = opUntil moveLeft moveRightUntil :: (a -> Bool) -> ListZipperOp' a moveRightUntil = opUntil moveRight moveLeftRightUntil :: (a -> Bool) -> ListZipperOp' a moveLeftRightUntil p = moveLeftUntil p moveRightUntil p moveRightLeftUntil :: (a -> Bool) -> ListZipperOp' a moveRightLeftUntil p = moveRightUntil p moveLeftUntil p opUntilThen :: ListZipperOp a x -> (a -> Bool) -> ListZipperOp' a opUntilThen o p = opUntil o p <* o moveLeftUntilThen :: (a -> Bool) -> ListZipperOp' a moveLeftUntilThen = opUntilThen moveLeft moveRightUntilThen :: (a -> Bool) -> ListZipperOp' a moveRightUntilThen = opUntilThen moveRight moveLeftRightUntilThen :: (a -> Bool) -> ListZipperOp' a moveLeftRightUntilThen p = moveLeftUntilThen p moveRightUntilThen p moveRightLeftUntilThen :: (a -> Bool) -> ListZipperOp' a moveRightLeftUntilThen p = moveRightUntilThen p moveLeftUntilThen p opWhileJust :: ListZipperOp' a -> ListZipper a -> ListZipper a opWhileJust o z = case execListZipperOp o z of Nothing -> z Just z' -> opWhileJust o z' deleteStepLeft :: ListZipperOp a a deleteStepLeft = ListZipperOp (\(ListZipper l x r) -> case l of [] -> Nothing h:t -> Just (ListZipper t h r, x) ) deleteStepRight :: ListZipperOp a a deleteStepRight = ListZipperOp (\(ListZipper l x r) -> case r of [] -> Nothing h:t -> Just (ListZipper l h t, x) ) modifyFocus :: (a -> a) -> ListZipperOp a a modifyFocus f = state (\(ListZipper l x r) -> (x, ListZipper l (f x) r)) setFocus :: a -> ListZipperOp a a setFocus = modifyFocus . pure deriveEq1 ''ListZipper deriveShow1 ''ListZipper