--------------------------------------------------------------------------------
-- |
-- Module      :  HGeometry.Measured.Size
-- Copyright   :  (C) Frank Staals
-- License     :  see the LICENSE file
-- Maintainer  :  Frank Staals
--------------------------------------------------------------------------------
module HGeometry.Measured.Size
  ( Count(Count)
  , Sized(Sized)
  ) where

import Control.DeepSeq
import Data.Coerce
import Data.Monoid (Sum(..))
import GHC.Generics (Generic)
import HGeometry.Measured.Class

--------------------------------------------------------------------------------

-- | Measured size or count. The result is always non-negative.
newtype Count a = Count Word
  deriving stock (Int -> Count a -> ShowS
[Count a] -> ShowS
Count a -> String
(Int -> Count a -> ShowS)
-> (Count a -> String) -> ([Count a] -> ShowS) -> Show (Count a)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall k (a :: k). Int -> Count a -> ShowS
forall k (a :: k). [Count a] -> ShowS
forall k (a :: k). Count a -> String
$cshowsPrec :: forall k (a :: k). Int -> Count a -> ShowS
showsPrec :: Int -> Count a -> ShowS
$cshow :: forall k (a :: k). Count a -> String
show :: Count a -> String
$cshowList :: forall k (a :: k). [Count a] -> ShowS
showList :: [Count a] -> ShowS
Show,ReadPrec [Count a]
ReadPrec (Count a)
Int -> ReadS (Count a)
ReadS [Count a]
(Int -> ReadS (Count a))
-> ReadS [Count a]
-> ReadPrec (Count a)
-> ReadPrec [Count a]
-> Read (Count a)
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
forall k (a :: k). ReadPrec [Count a]
forall k (a :: k). ReadPrec (Count a)
forall k (a :: k). Int -> ReadS (Count a)
forall k (a :: k). ReadS [Count a]
$creadsPrec :: forall k (a :: k). Int -> ReadS (Count a)
readsPrec :: Int -> ReadS (Count a)
$creadList :: forall k (a :: k). ReadS [Count a]
readList :: ReadS [Count a]
$creadPrec :: forall k (a :: k). ReadPrec (Count a)
readPrec :: ReadPrec (Count a)
$creadListPrec :: forall k (a :: k). ReadPrec [Count a]
readListPrec :: ReadPrec [Count a]
Read,Count a -> Count a -> Bool
(Count a -> Count a -> Bool)
-> (Count a -> Count a -> Bool) -> Eq (Count a)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall k (a :: k). Count a -> Count a -> Bool
$c== :: forall k (a :: k). Count a -> Count a -> Bool
== :: Count a -> Count a -> Bool
$c/= :: forall k (a :: k). Count a -> Count a -> Bool
/= :: Count a -> Count a -> Bool
Eq,Eq (Count a)
Eq (Count a) =>
(Count a -> Count a -> Ordering)
-> (Count a -> Count a -> Bool)
-> (Count a -> Count a -> Bool)
-> (Count a -> Count a -> Bool)
-> (Count a -> Count a -> Bool)
-> (Count a -> Count a -> Count a)
-> (Count a -> Count a -> Count a)
-> Ord (Count a)
Count a -> Count a -> Bool
Count a -> Count a -> Ordering
Count a -> Count a -> Count a
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 k (a :: k). Eq (Count a)
forall k (a :: k). Count a -> Count a -> Bool
forall k (a :: k). Count a -> Count a -> Ordering
forall k (a :: k). Count a -> Count a -> Count a
$ccompare :: forall k (a :: k). Count a -> Count a -> Ordering
compare :: Count a -> Count a -> Ordering
$c< :: forall k (a :: k). Count a -> Count a -> Bool
< :: Count a -> Count a -> Bool
$c<= :: forall k (a :: k). Count a -> Count a -> Bool
<= :: Count a -> Count a -> Bool
$c> :: forall k (a :: k). Count a -> Count a -> Bool
> :: Count a -> Count a -> Bool
$c>= :: forall k (a :: k). Count a -> Count a -> Bool
>= :: Count a -> Count a -> Bool
$cmax :: forall k (a :: k). Count a -> Count a -> Count a
max :: Count a -> Count a -> Count a
$cmin :: forall k (a :: k). Count a -> Count a -> Count a
min :: Count a -> Count a -> Count a
Ord,(forall x. Count a -> Rep (Count a) x)
-> (forall x. Rep (Count a) x -> Count a) -> Generic (Count a)
forall x. Rep (Count a) x -> Count a
forall x. Count a -> Rep (Count a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall k (a :: k) x. Rep (Count a) x -> Count a
forall k (a :: k) x. Count a -> Rep (Count a) x
$cfrom :: forall k (a :: k) x. Count a -> Rep (Count a) x
from :: forall x. Count a -> Rep (Count a) x
$cto :: forall k (a :: k) x. Rep (Count a) x -> Count a
to :: forall x. Rep (Count a) x -> Count a
Generic)
  deriving newtype (Count a -> ()
(Count a -> ()) -> NFData (Count a)
forall a. (a -> ()) -> NFData a
forall k (a :: k). Count a -> ()
$crnf :: forall k (a :: k). Count a -> ()
rnf :: Count a -> ()
NFData)
  deriving (NonEmpty (Count a) -> Count a
Count a -> Count a -> Count a
(Count a -> Count a -> Count a)
-> (NonEmpty (Count a) -> Count a)
-> (forall b. Integral b => b -> Count a -> Count a)
-> Semigroup (Count a)
forall b. Integral b => b -> Count a -> Count a
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
forall k (a :: k). NonEmpty (Count a) -> Count a
forall k (a :: k). Count a -> Count a -> Count a
forall k (a :: k) b. Integral b => b -> Count a -> Count a
$c<> :: forall k (a :: k). Count a -> Count a -> Count a
<> :: Count a -> Count a -> Count a
$csconcat :: forall k (a :: k). NonEmpty (Count a) -> Count a
sconcat :: NonEmpty (Count a) -> Count a
$cstimes :: forall k (a :: k) b. Integral b => b -> Count a -> Count a
stimes :: forall b. Integral b => b -> Count a -> Count a
Semigroup,Semigroup (Count a)
Count a
Semigroup (Count a) =>
Count a
-> (Count a -> Count a -> Count a)
-> ([Count a] -> Count a)
-> Monoid (Count a)
[Count a] -> Count a
Count a -> Count a -> Count a
forall a.
Semigroup a =>
a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
forall k (a :: k). Semigroup (Count a)
forall k (a :: k). Count a
forall k (a :: k). [Count a] -> Count a
forall k (a :: k). Count a -> Count a -> Count a
$cmempty :: forall k (a :: k). Count a
mempty :: Count a
$cmappend :: forall k (a :: k). Count a -> Count a -> Count a
mappend :: Count a -> Count a -> Count a
$cmconcat :: forall k (a :: k). [Count a] -> Count a
mconcat :: [Count a] -> Count a
Monoid) via Sum Word

instance Measured Count a where
  measure :: a -> Count a
measure = Count a -> a -> Count a
forall a b. a -> b -> a
const (Count a -> a -> Count a) -> Count a -> a -> Count a
forall a b. (a -> b) -> a -> b
$ Word -> Count a
forall {k} (a :: k). Word -> Count a
Count Word
1

instance CanInsert Count a where
  insertMeasure :: a -> Count a -> Count a
insertMeasure a
_ (Count Word
n) = Word -> Count a
forall {k} (a :: k). Word -> Count a
Count (Word
nWord -> Word -> Word
forall a. Num a => a -> a -> a
+Word
1)

instance CanDelete Count a where
  deleteMeasure :: a -> Count a -> Maybe (Count a)
deleteMeasure a
_ (Count Word
n) = Count a -> Maybe (Count a)
forall a. a -> Maybe a
Just (Count a -> Maybe (Count a))
-> (Word -> Count a) -> Word -> Maybe (Count a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word -> Count a
forall {k} (a :: k). Word -> Count a
Count (Word -> Maybe (Count a)) -> Word -> Maybe (Count a)
forall a b. (a -> b) -> a -> b
$ Word -> Word -> Word
forall a. Ord a => a -> a -> a
max Word
0 (Word
nWord -> Word -> Word
forall a. Num a => a -> a -> a
-Word
1)

--------------------------------------------------------------------------------

-- -- | Newtype wrapper for things for which we can measure the size
-- newtype Elem a = Elem { _unElem :: a }
--                deriving (Show,Read,Eq,Ord,Functor,Foldable,Traversable)

-- instance Measured Size (Elem a) where
--   measure _ = 1

--------------------------------------------------------------------------------

-- | Things that have a size
data Sized a = Sized {-# UNPACK #-} !(Count a) a
             deriving (Int -> Sized a -> ShowS
[Sized a] -> ShowS
Sized a -> String
(Int -> Sized a -> ShowS)
-> (Sized a -> String) -> ([Sized a] -> ShowS) -> Show (Sized a)
forall a. Show a => Int -> Sized a -> ShowS
forall a. Show a => [Sized a] -> ShowS
forall a. Show a => Sized a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall a. Show a => Int -> Sized a -> ShowS
showsPrec :: Int -> Sized a -> ShowS
$cshow :: forall a. Show a => Sized a -> String
show :: Sized a -> String
$cshowList :: forall a. Show a => [Sized a] -> ShowS
showList :: [Sized a] -> ShowS
Show,Sized a -> Sized a -> Bool
(Sized a -> Sized a -> Bool)
-> (Sized a -> Sized a -> Bool) -> Eq (Sized a)
forall a. Eq a => Sized a -> Sized a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall a. Eq a => Sized a -> Sized a -> Bool
== :: Sized a -> Sized a -> Bool
$c/= :: forall a. Eq a => Sized a -> Sized a -> Bool
/= :: Sized a -> Sized a -> Bool
Eq,Eq (Sized a)
Eq (Sized a) =>
(Sized a -> Sized a -> Ordering)
-> (Sized a -> Sized a -> Bool)
-> (Sized a -> Sized a -> Bool)
-> (Sized a -> Sized a -> Bool)
-> (Sized a -> Sized a -> Bool)
-> (Sized a -> Sized a -> Sized a)
-> (Sized a -> Sized a -> Sized a)
-> Ord (Sized a)
Sized a -> Sized a -> Bool
Sized a -> Sized a -> Ordering
Sized a -> Sized a -> Sized a
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 (Sized a)
forall a. Ord a => Sized a -> Sized a -> Bool
forall a. Ord a => Sized a -> Sized a -> Ordering
forall a. Ord a => Sized a -> Sized a -> Sized a
$ccompare :: forall a. Ord a => Sized a -> Sized a -> Ordering
compare :: Sized a -> Sized a -> Ordering
$c< :: forall a. Ord a => Sized a -> Sized a -> Bool
< :: Sized a -> Sized a -> Bool
$c<= :: forall a. Ord a => Sized a -> Sized a -> Bool
<= :: Sized a -> Sized a -> Bool
$c> :: forall a. Ord a => Sized a -> Sized a -> Bool
> :: Sized a -> Sized a -> Bool
$c>= :: forall a. Ord a => Sized a -> Sized a -> Bool
>= :: Sized a -> Sized a -> Bool
$cmax :: forall a. Ord a => Sized a -> Sized a -> Sized a
max :: Sized a -> Sized a -> Sized a
$cmin :: forall a. Ord a => Sized a -> Sized a -> Sized a
min :: Sized a -> Sized a -> Sized a
Ord,(forall x. Sized a -> Rep (Sized a) x)
-> (forall x. Rep (Sized a) x -> Sized a) -> Generic (Sized a)
forall x. Rep (Sized a) x -> Sized a
forall x. Sized a -> Rep (Sized a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (Sized a) x -> Sized a
forall a x. Sized a -> Rep (Sized a) x
$cfrom :: forall a x. Sized a -> Rep (Sized a) x
from :: forall x. Sized a -> Rep (Sized a) x
$cto :: forall a x. Rep (Sized a) x -> Sized a
to :: forall x. Rep (Sized a) x -> Sized a
Generic)
instance NFData a => NFData (Sized a)

instance Functor Sized where
  fmap :: forall a b. (a -> b) -> Sized a -> Sized b
fmap a -> b
f (Sized Count a
c a
a) = Count b -> b -> Sized b
forall a. Count a -> a -> Sized a
Sized (Count a -> Count b
forall a b. Coercible a b => a -> b
coerce Count a
c) (a -> b
f a
a)
instance Foldable Sized where
  foldMap :: forall m a. Monoid m => (a -> m) -> Sized a -> m
foldMap a -> m
f (Sized Count a
_ a
a) = a -> m
f a
a
instance Traversable Sized where
  traverse :: forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> Sized a -> f (Sized b)
traverse a -> f b
f (Sized Count a
c a
a) = Count b -> b -> Sized b
forall a. Count a -> a -> Sized a
Sized (Count a -> Count b
forall a b. Coercible a b => a -> b
coerce Count a
c) (b -> Sized b) -> f b -> f (Sized b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a -> f b
f a
a

instance Semigroup a => Semigroup (Sized a) where
  (Sized Count a
i a
a) <> :: Sized a -> Sized a -> Sized a
<> (Sized Count a
j a
b) = Count a -> a -> Sized a
forall a. Count a -> a -> Sized a
Sized (Count a
i Count a -> Count a -> Count a
forall a. Semigroup a => a -> a -> a
<> Count a
j) (a
a a -> a -> a
forall a. Semigroup a => a -> a -> a
<> a
b)

instance Monoid a => Monoid (Sized a) where
  mempty :: Sized a
mempty = Count a -> a -> Sized a
forall a. Count a -> a -> Sized a
Sized Count a
forall a. Monoid a => a
mempty a
forall a. Monoid a => a
mempty

-- instance Semigroup a => Measured Size (Sized a) where
--   measure (Sized i _) = i