data-carousel-0.1.0.0: src/Data/Carousel.hs
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE UnicodeSyntax #-}
-- |
-- Module: Data.Carousel
-- Copyright: Copyright © 2014 AlephCloud Systems, Inc.
-- License: MIT
-- Maintainer: Jon Sterling <jsterling@alephcloud.com>
-- Stability: experimental
--
module Data.Carousel
( Carousel
, empty
, cursor
, moveLeft
, moveRight
, dropCursor
, nub
, append
, clSequence
, clList
) where
import Control.Lens
import qualified Data.Foldable as F
import qualified Data.List as L
import qualified Data.Sequence as S
newtype Carousel α
= Carousel
{ _clSequence ∷ S.Seq α
} deriving (Show, Eq)
instance Functor Carousel where
fmap f (Carousel sq) = Carousel $ fmap f sq
instance F.Foldable Carousel where
foldMap f (Carousel sq) = F.foldMap f sq
instance Traversable Carousel where
traverse f (Carousel sq) = fmap Carousel (traverse f sq)
clSequence ∷ Iso (Carousel α) (Carousel β) (S.Seq α) (S.Seq β)
clSequence = iso _clSequence Carousel
clList ∷ Iso (Carousel α) (Carousel β) [α] [β]
clList = clSequence . iso F.toList S.fromList
-- | There is guaranteed to be a cursor so long as the carousel is non-empty.
cursor ∷ Traversal' (Carousel α) α
cursor = clSequence . _head
-- | You can delete the cursor from the carousel; the items to its right will
-- move one over to the left.
dropCursor
∷ Carousel α
→ Carousel α
dropCursor = clSequence %~ (^. _tail)
-- | The carousel may be rotated to the right; this operation is written so as
-- to always guarantee the presence of a cursor in a non-empty carousel.
moveRight
∷ Carousel α
→ Carousel α
moveRight = clSequence %~ rotate . S.viewl
where
rotate
∷ S.ViewL α
→ S.Seq α
rotate S.EmptyL = S.empty
rotate (x S.:< xs) = xs S.|> x
-- | The carousel may be rotated to the left; this operation is written so as
-- to always guarantee the presence of a cursor in a non-empty carousel.
moveLeft
∷ Carousel α
→ Carousel α
moveLeft = clSequence %~ rotate . S.viewr
where
rotate
∷ S.ViewR α
→ S.Seq α
rotate S.EmptyR = S.empty
rotate (xs S.:> x) = x S.<| xs
-- | The empty carousel.
empty
∷ Carousel α
empty = Carousel S.empty
-- | Append a list of elements to the right side of the carousel.
append
∷ [α]
→ Carousel α
→ Carousel α
append xs = clSequence %~ (S.>< S.fromList xs)
-- | Remove all duplicate elements from the carousel. (TODO: this is inefficient)
nub
∷ Eq α
⇒ Carousel α
→ Carousel α
nub = clList %~ L.nub