-- |
-- Module      : Numeric.QuadraticIrrational.CyclicList
-- Description : A container for a possibly cyclic list.
-- Copyright   : © 2014 Johan Kiviniemi
-- License     : MIT
-- Maintainer  : Johan Kiviniemi <devel@johan.kiviniemi.name>
-- Stability   : provisional
-- Portability : portable

{-# LANGUAGE DeriveFunctor     #-}

module Numeric.QuadraticIrrational.CyclicList
  ( CycList(..)
  ) where

import Data.Foldable (toList)
import Data.Monoid ((<>))

-- | A container for a possibly cyclic list.
--
-- $setup
-- >>> import Data.Foldable (toList)
--
-- >>> toList (CycList "hello" "")
-- "hello"
--
-- >>> take 70 (toList (CycList "prefix " "cycle"))
-- "prefix cyclecyclecyclecyclecyclecyclecyclecyclecyclecyclecyclecyclecyc"
data CycList a = CycList [a] [a]
  deriving (CycList a -> CycList a -> Bool
forall a. Eq a => CycList a -> CycList a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: CycList a -> CycList a -> Bool
$c/= :: forall a. Eq a => CycList a -> CycList a -> Bool
== :: CycList a -> CycList a -> Bool
$c== :: forall a. Eq a => CycList a -> CycList a -> Bool
Eq, CycList a -> CycList a -> Bool
CycList a -> CycList a -> Ordering
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall {a}. Ord a => Eq (CycList a)
forall a. Ord a => CycList a -> CycList a -> Bool
forall a. Ord a => CycList a -> CycList a -> Ordering
forall a. Ord a => CycList a -> CycList a -> CycList a
min :: CycList a -> CycList a -> CycList a
$cmin :: forall a. Ord a => CycList a -> CycList a -> CycList a
max :: CycList a -> CycList a -> CycList a
$cmax :: forall a. Ord a => CycList a -> CycList a -> CycList a
>= :: CycList a -> CycList a -> Bool
$c>= :: forall a. Ord a => CycList a -> CycList a -> Bool
> :: CycList a -> CycList a -> Bool
$c> :: forall a. Ord a => CycList a -> CycList a -> Bool
<= :: CycList a -> CycList a -> Bool
$c<= :: forall a. Ord a => CycList a -> CycList a -> Bool
< :: CycList a -> CycList a -> Bool
$c< :: forall a. Ord a => CycList a -> CycList a -> Bool
compare :: CycList a -> CycList a -> Ordering
$ccompare :: forall a. Ord a => CycList a -> CycList a -> Ordering
Ord, ReadPrec [CycList a]
ReadPrec (CycList a)
ReadS [CycList a]
forall a. Read a => ReadPrec [CycList a]
forall a. Read a => ReadPrec (CycList a)
forall a. Read a => Int -> ReadS (CycList a)
forall a. Read a => ReadS [CycList a]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [CycList a]
$creadListPrec :: forall a. Read a => ReadPrec [CycList a]
readPrec :: ReadPrec (CycList a)
$creadPrec :: forall a. Read a => ReadPrec (CycList a)
readList :: ReadS [CycList a]
$creadList :: forall a. Read a => ReadS [CycList a]
readsPrec :: Int -> ReadS (CycList a)
$creadsPrec :: forall a. Read a => Int -> ReadS (CycList a)
Read, Int -> CycList a -> ShowS
forall a. Show a => Int -> CycList a -> ShowS
forall a. Show a => [CycList a] -> ShowS
forall a. Show a => CycList a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [CycList a] -> ShowS
$cshowList :: forall a. Show a => [CycList a] -> ShowS
show :: CycList a -> String
$cshow :: forall a. Show a => CycList a -> String
showsPrec :: Int -> CycList a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> CycList a -> ShowS
Show, forall a b. a -> CycList b -> CycList a
forall a b. (a -> b) -> CycList a -> CycList b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> CycList b -> CycList a
$c<$ :: forall a b. a -> CycList b -> CycList a
fmap :: forall a b. (a -> b) -> CycList a -> CycList b
$cfmap :: forall a b. (a -> b) -> CycList a -> CycList b
Functor)

instance Foldable CycList where
  toList :: forall a. CycList a -> [a]
toList (CycList [a]
as []) = [a]
as
  toList (CycList [a]
as [a]
bs) = [a]
as forall a. Semigroup a => a -> a -> a
<> forall a. [a] -> [a]
cycle [a]
bs

  foldMap :: forall m a. Monoid m => (a -> m) -> CycList a -> m
foldMap a -> m
f (CycList [a]
as []) = forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap a -> m
f [a]
as
  foldMap a -> m
f (CycList [a]
as [a]
bs) = forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap a -> m
f [a]
as forall a. Semigroup a => a -> a -> a
<> forall {t}. Semigroup t => t -> t
cycleAppend (forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap a -> m
f [a]
bs)
    where
      cycleAppend :: t -> t
cycleAppend t
x = t
x forall a. Semigroup a => a -> a -> a
<> t -> t
cycleAppend t
x