{-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE TypeFamilies #-} module Data.ListZipper( ListZipper(..) , AsListZipper(..) , HasListZipper(..) , leftz' , rightz' , leftzrightz , rightzleftz , zipper , zipper0L , zipper0L' , zipper0R , zipper0R' , list , zipperIndices , moveStart , moveEnd , atStart , atEnd , moveLeftLoop , moveRightLoop , insertMoveLeft , insertMoveRight , ListZipperOp(..) , ListZipperOp' , unListZipperOp' , HasListZipperOp(..) , AsListZipperOp(..) , unpureListZipperOp , mkListZipperOp , mkListZipperOp' , moveLeft , moveRight , opUntil , moveLeftUntil , moveRightUntil , moveLeftRightUntil , moveRightLeftUntil , opWhileJust , deleteStepLeft , deleteStepRight ) 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) 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.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 . (unListZipperOp' 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) moveStart :: ListZipper a -> ListZipper a moveStart = opWhileJust moveLeft moveEnd :: ListZipper a -> ListZipper a moveEnd = opWhileJust moveRight 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) (unListZipperOp' moveLeft z) moveRightLoop :: ListZipper a -> ListZipper a moveRightLoop z = fromMaybe (moveStart z) (unListZipperOp' moveRight z) insertMoveLeft :: a -> ListZipper a -> ListZipper a insertMoveLeft a (ListZipper l x r) = ListZipper (a:l) x r insertMoveRight :: a -> ListZipper a -> ListZipper a insertMoveRight a (ListZipper l x r) = ListZipper l x (a:r) ---- newtype ListZipperOp x a = ListZipperOp (ListZipper x -> Maybe (ListZipper x, a)) type ListZipperOp' x = ListZipperOp x () unListZipperOp' :: ListZipperOp' x -> ListZipper x -> Maybe (ListZipper x) unListZipperOp' o z = fmap (^. _1) (z & o ^. _Wrapped) instance ListZipperOp x a ~ t => Rewrapped (ListZipperOp x' a') t instance Wrapped (ListZipperOp x' a') where type Unwrapped (ListZipperOp x' a') = ListZipper x' -> Maybe (ListZipper x', a') _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 x) where fmap f (ListZipperOp k) = ListZipperOp (fmap (fmap f) . k) instance Apply (ListZipperOp x) where ListZipperOp j <.> ListZipperOp k = ListZipperOp (\z -> j z >>= \(z', f) -> k z' >>= \(z'', a) -> pure (z'', f a) ) instance Applicative (ListZipperOp x) where (<*>) = (<.>) pure a = ListZipperOp (\z -> pure (z, a)) instance Bind (ListZipperOp x) where ListZipperOp j >>- f = ListZipperOp (\z -> j z >>- \(z', a) -> z' & f a ^. _Wrapped ) instance Alt (ListZipperOp x) where ListZipperOp j ListZipperOp k = ListZipperOp (\z -> j z k z) instance Alternative (ListZipperOp x) where (<|>) = () empty = ListZipperOp (pure empty) instance Monad (ListZipperOp x) where (>>=) = (>>-) return = pure instance MonadPlus (ListZipperOp x) where ListZipperOp j `mplus` ListZipperOp k = ListZipperOp (\z -> j z `mplus` k z) mzero = ListZipperOp (pure mzero) instance Semigroup (ListZipperOp x y) where ListZipperOp j <> ListZipperOp k = ListZipperOp (\z -> j z k z) instance Monoid (ListZipperOp x y) where mappend = (<>) mempty = ListZipperOp (pure Nothing) instance MonadState (ListZipper x) (ListZipperOp x) 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 x) (ListZipperOp x) 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 x) where mfix f = ListZipperOp (\z -> mfix (\ ~(_, a) -> z & f a ^. _Wrapped) ) instance MonadFail (ListZipperOp x) where fail s = ListZipperOp (\_ -> Fail.fail s ) instance MonadError () (ListZipperOp x) where throwError () = ListZipperOp (\_ -> Nothing) catchError (ListZipperOp k) f = ListZipperOp (\z -> k z (z & f () ^. _Wrapped) ) unpureListZipperOp :: ListZipperOp x a -> ListZipper x -> ListZipper x unpureListZipperOp (ListZipperOp x) z = case x z of Nothing -> z Just (z', _) -> z' mkListZipperOp :: (ListZipper x -> Maybe a) -> ListZipperOp x a mkListZipperOp f = ListZipperOp (\z -> (\a -> (z, a)) <$> f z ) mkListZipperOp' :: (ListZipper x -> Maybe (ListZipper x)) -> ListZipperOp' x mkListZipperOp' f = ListZipperOp (\s -> (\s' -> (s', ())) <$> f s) 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) ) opUntil :: ListZipperOp x () -> (x -> Bool) -> ListZipperOp x () opUntil o p = ListZipperOp (\z -> let go z' = let x = z' ^. focus in if p x then Just (z', ()) else go =<< unListZipperOp' o z' in go z ) 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 opWhileJust :: ListZipperOp' a -> ListZipper a -> ListZipper a opWhileJust o z = case unListZipperOp' o z of Nothing -> z Just z' -> opWhileJust o z' deleteStepLeft :: ListZipperOp' a deleteStepLeft = mkListZipperOp' (\z -> let l = z ^. leftz r = z ^. rightz in case l of [] -> Nothing h:t -> Just (ListZipper t h r) ) deleteStepRight :: ListZipperOp' a deleteStepRight = mkListZipperOp' (\z -> let l = z ^. leftz r = z ^. rightz in case r of [] -> Nothing h:t -> Just (ListZipper l h t) ) deriveEq1 ''ListZipper deriveShow1 ''ListZipper