{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DeriveFoldable, DeriveTraversable #-} module Play.Engine.ListZipper where import GHC.Generics import Control.DeepSeq data ListZipper a = ListZipper [a] !a [a] deriving (Eq, Ord, Show, Read, Functor, Foldable, Generic, NFData) instance Traversable ListZipper where traverse f (ListZipper p c n) = ListZipper <$> fmap reverse (traverse f (reverse p)) <*> f c <*> traverse f n get :: ListZipper a -> a get (ListZipper _ x _) = x overCurr :: (a -> a) -> ListZipper a -> ListZipper a overCurr f (ListZipper p x n) = ListZipper p (f x) n nextStop :: ListZipper a -> ListZipper a nextStop = \case ListZipper prev curr (n:next) -> ListZipper (curr : prev) n next l -> l nextCycle :: ListZipper a -> ListZipper a nextCycle = \case ListZipper prev curr (n:next) -> ListZipper (curr : prev) n next ListZipper prev curr [] -> let (curr' : next) = reverse $ curr : prev in ListZipper [] curr' next prevCycle :: ListZipper a -> ListZipper a prevCycle = \case ListZipper (p:prev) curr next -> ListZipper prev p (curr : next) ListZipper [] curr next -> let (curr' : prev) = reverse $ curr : next in ListZipper prev curr' [] first :: ListZipper a -> a first = \case ListZipper [] curr _ -> curr ListZipper prev _ _ -> Prelude.last prev last :: ListZipper a -> a last = \case ListZipper _ curr [] -> curr ListZipper _ _ next -> Prelude.last next diffMapM :: Applicative f => (a -> f b) -> (a -> f b) -> ListZipper a -> f (ListZipper b) diffMapM restF currF (ListZipper prev curr next) = ListZipper <$> traverse restF prev <*> currF curr <*> traverse restF next addIndex :: ListZipper a -> ListZipper (Int, a) addIndex = \case ListZipper prev curr next -> ListZipper (reverse $ zip [0..] $ reverse prev) (length prev, curr) (zip [length prev + 1..] next)