{-# 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