{-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE UndecidableInstances #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module Data.Strict.Sequence.Lens ( viewL , viewR , slicedTo , slicedFrom , sliced , seqOf ) where import Control.Lens import qualified Data.Foldable as Foldable import qualified Data.Strict.Sequence as Seq import Data.Strict.Sequence (Seq, ViewL(EmptyL), ViewR(EmptyR), (><), viewl, viewr) #if !MIN_VERSION_lens(5,0,0) instance FunctorWithIndex Int Seq where imap = Seq.mapWithIndex {-# INLINE imap #-} instance FoldableWithIndex Int Seq where ifoldMap = Seq.foldMapWithIndex {-# INLINE ifoldMap #-} ifoldr = Seq.foldrWithIndex {-# INLINE ifoldr #-} ifoldl f = Seq.foldlWithIndex (flip f) {-# INLINE ifoldl #-} instance TraversableWithIndex Int Seq where itraverse = Seq.traverseWithIndex {-# INLINE itraverse #-} #endif type instance Index (Seq a) = Int type instance IxValue (Seq a) = a instance Ixed (Seq a) where -- This is slightly different from lens' definition to make our ixTest work. -- It is analogous to how Map.ix is defined. ix i f m = case Seq.lookup i m of Nothing -> pure m Just v -> f v <&> \a -> Seq.update i a m {-# INLINE ix #-} instance AsEmpty (Seq a) where _Empty = nearly Seq.empty Seq.null {-# INLINE _Empty #-} instance Each (Seq a) (Seq b) a b where each = traversed {-# INLINE each #-} instance (t ~ Seq a') => Rewrapped (Seq a) t instance Wrapped (Seq a) where type Unwrapped (Seq a) = [a] _Wrapped' = iso Foldable.toList Seq.fromList {-# INLINE _Wrapped' #-} instance Cons (Seq a) (Seq b) a b where _Cons = prism (uncurry (Seq.<|)) $ \aas -> case viewl aas of a Seq.:< as -> Right (a, as) EmptyL -> Left mempty {-# INLINE _Cons #-} instance Snoc (Seq a) (Seq b) a b where _Snoc = prism (uncurry (Seq.|>)) $ \aas -> case viewr aas of as Seq.:> a -> Right (as, a) EmptyR -> Left mempty {-# INLINE _Snoc #-} instance Reversing (Seq a) where reversing = Seq.reverse -- | Analogous to 'Data.Sequence.Lens.viewL'. viewL :: Iso (Seq a) (Seq b) (ViewL a) (ViewL b) viewL = iso viewl $ \ xs -> case xs of EmptyL -> mempty a Seq.:< as -> a Seq.<| as {-# INLINE viewL #-} -- | Analogous to 'Data.Sequence.Lens.viewR'. viewR :: Iso (Seq a) (Seq b) (ViewR a) (ViewR b) viewR = iso viewr $ \xs -> case xs of EmptyR -> mempty as Seq.:> a -> as Seq.|> a {-# INLINE viewR #-} -- | Analogous to 'Data.Sequence.Lens.slicedTo'. slicedTo :: Int -> IndexedTraversal' Int (Seq a) a slicedTo n f m = case Seq.splitAt n m of (l,r) -> (>< r) <$> itraverse (indexed f) l {-# INLINE slicedTo #-} -- | Analogous to 'Data.Sequence.Lens.slicedFrom'. slicedFrom :: Int -> IndexedTraversal' Int (Seq a) a slicedFrom n f m = case Seq.splitAt n m of (l,r) -> (l ><) <$> itraverse (indexed f . (+n)) r {-# INLINE slicedFrom #-} -- | Analogous to 'Data.Sequence.Lens.sliced'. sliced :: Int -> Int -> IndexedTraversal' Int (Seq a) a sliced i j f s = case Seq.splitAt i s of (l,mr) -> case Seq.splitAt (j-i) mr of (m, r) -> itraverse (indexed f . (+i)) m <&> \n -> l >< n >< r {-# INLINE sliced #-} -- | Analogous to 'Data.Sequence.Lens.seqOf'. seqOf :: Getting (Seq a) s a -> s -> Seq a seqOf l = views l Seq.singleton {-# INLINE seqOf #-}