module Buchhaltung.Zipper
(module Buchhaltung.Zipper
, E.NonEmpty(..)
, E.nonEmpty
) where
import Data.List.NonEmpty (NonEmpty(..))
import qualified Data.List.NonEmpty as E
import Data.Monoid
data Zipper a = LZ { past :: E.NonEmpty a
, future :: [a]
}
present :: Zipper a -> a
present = E.head . past
instance Functor Zipper where
fmap f (LZ ps fs) = LZ (E.map f ps) (map f fs)
integrate' :: Zipper a -> E.NonEmpty a
integrate' (LZ p f) = E.fromList $ reverse (E.toList p) <> f
integrate :: Zipper a -> [a]
integrate = E.toList . integrate'
differentiate :: E.NonEmpty a -> Zipper a
differentiate (x :| xs) = LZ (pure x) xs
back :: Zipper a -> Zipper a
back z@(LZ (_ :| []) _) = z
back (LZ (pr :| (np:ps)) fs) = LZ (np :| ps) (pr:fs)
fwd :: Zipper a -> Zipper a
fwd z@(LZ _ []) = z
fwd (LZ ps (f:fs)) = LZ (f E.<| ps) fs
modifyPresent :: (a -> a) -> Zipper a -> Zipper a
modifyPresent f z@LZ{past=(present :| past)} = z { past = (f present :| past) }
modifyBack :: ([a] -> [a]) -> Zipper a -> Zipper a
modifyBack f z@LZ{ past=(pr :| ps) } = z { past = (pr :| f ps) }
modifyFwd :: ([a] -> [a]) -> Zipper a -> Zipper a
modifyFwd f z = z { future = f (future z) }
delete :: Zipper a -> Zipper a
delete (LZ (_ :| []) [] ) = error "empty zipper not allowed"
delete (LZ (_ :| (np:past)) [] ) = LZ (np :| past) []
delete (LZ (_ :| past) (np:f) ) = LZ (np :| past) f
insback :: a -> Zipper a -> Zipper a
insback x (LZ (pr :| ps) fs) = LZ (x :| ps) (pr:fs)
insfwd :: a -> Zipper a -> Zipper a
insfwd x (LZ ps fs) = LZ (x E.<| ps) fs