{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE NoImplicitPrelude #-}

module Natural
  ( Natural,
    HasNatural (..),
    AsNatural (..),
    ProductNatural (..),
    MaxNatural (..),
    MinNatural (..),
    zero,
    zero',
    successor,
    successor',
    plus,
    multiply,
    power,
    zeroOr,
    length,
    replicate,
    take,
    drop,
    splitAt,
    (!!),
    findIndices,
    findIndex,
    elemIndices,
    elemIndex,
    minus,
    list,
    Positive,
    HasPositive (..),
    AsPositive (..),
    SumPositive (..),
    MaxPositive (..),
    MinPositive (..),
    naturalPositive,
    one,
    one',
    successor1,
    successor1',
    successorW,
    plus1,
    multiply1,
    power1,
    oneOr,
    length1,
    replicate1,
    take1,
    drop1,
    splitAt1,
    (!!!),
    findIndices1,
    findIndex1,
    elemIndices1,
    elemIndex1,
    minus1,
    list1,
    plusone,
    minusone,
    NotZero (..),
    HasNotZero (..),
    AsNotZero (..),
    SumNotZero (..),
    MaxNotZero (..),
    MinNotZero (..),
    positiveNotZero,
    negativeNotZero,
    notZeroPositive,
    notZeroInteger,
    isPositive,
    isNegative,
    negateNZ,
    absoluteNZ,
    signumNZ,
    plusNZ,
    multiplyNZ,
    notZeroOr,
    toJsonNatural,
    parseJsonNatural,
    toJsonPositive,
    parseJsonPositive,
    toJsonNotZero,
    parseJsonNotZero,
  )
where

import Control.Applicative (Const, pure)
import Control.Category (id, (.))
import Control.Lens (Iso', Lens', Prism', Rewrapped, Wrapped (Unwrapped, _Wrapped'), iso, prism', (#), (^.), (^?), _Wrapped)
import Control.Monad (fail, (>>=))
import Data.Aeson.Types
  ( FromJSON (parseJSON),
    Parser,
    ToJSON (toEncoding, toJSON),
    Value,
  )
import Data.Bool (Bool (False, True), not, (&&))
import Data.Eq (Eq ((==)))
import Data.Foldable (Foldable (foldl'))
import Data.Function (const)
import Data.Functor.Identity (Identity)
import Data.Int (Int)
import Data.List (filter, iterate, map, repeat, zip)
import Data.List.NonEmpty (NonEmpty ((:|)))
import qualified Data.List.NonEmpty as NonEmpty (filter, iterate, zip)
import Data.Maybe (Maybe (Just, Nothing), fromMaybe, listToMaybe)
import Data.Monoid (Monoid (mappend, mempty))
import Data.Ord (Ord (compare, (<), (<=)), max, min)
import Data.Semigroup (Semigroup ((<>)))
import Data.Semigroup.Foldable (Foldable1 (foldMap1))
import Data.Tuple (fst, snd)
import Data.Word (Word)
import Prelude (Integer, Integral, Show, abs, fromIntegral, negate, (*), (+), (-), (^))

-- $setup
-- >>> :set -XOverloadedStrings
-- >>> import Control.Lens((^?), (^.), (#), _Wrapped', _Wrapped)
-- >>> import Data.Aeson(encode, decode, fromJSON, Result(..))
-- >>> import Data.Aeson.Types(parse, Value(Number))
-- >>> import Data.List.NonEmpty(NonEmpty(..))
-- >>> import Data.Maybe(fromJust)
-- >>> let nat n = fromJust ((n :: Integer) ^? _Natural)
-- >>> let pos n = fromJust ((n :: Integer) ^? _Positive)

-- | A natural number (>= 0) represented as a newtype over 'Integer'.
--
-- >>> nat 0
-- Natural 0
--
-- >>> nat 5
-- Natural 5
newtype Natural
  = Natural
      Integer
  deriving (Natural -> Natural -> Bool
(Natural -> Natural -> Bool)
-> (Natural -> Natural -> Bool) -> Eq Natural
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Natural -> Natural -> Bool
== :: Natural -> Natural -> Bool
$c/= :: Natural -> Natural -> Bool
/= :: Natural -> Natural -> Bool
Eq, Eq Natural
Eq Natural =>
(Natural -> Natural -> Ordering)
-> (Natural -> Natural -> Bool)
-> (Natural -> Natural -> Bool)
-> (Natural -> Natural -> Bool)
-> (Natural -> Natural -> Bool)
-> (Natural -> Natural -> Natural)
-> (Natural -> Natural -> Natural)
-> Ord Natural
Natural -> Natural -> Bool
Natural -> Natural -> Ordering
Natural -> Natural -> Natural
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
$ccompare :: Natural -> Natural -> Ordering
compare :: Natural -> Natural -> Ordering
$c< :: Natural -> Natural -> Bool
< :: Natural -> Natural -> Bool
$c<= :: Natural -> Natural -> Bool
<= :: Natural -> Natural -> Bool
$c> :: Natural -> Natural -> Bool
> :: Natural -> Natural -> Bool
$c>= :: Natural -> Natural -> Bool
>= :: Natural -> Natural -> Bool
$cmax :: Natural -> Natural -> Natural
max :: Natural -> Natural -> Natural
$cmin :: Natural -> Natural -> Natural
min :: Natural -> Natural -> Natural
Ord, Int -> Natural -> ShowS
[Natural] -> ShowS
Natural -> String
(Int -> Natural -> ShowS)
-> (Natural -> String) -> ([Natural] -> ShowS) -> Show Natural
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Natural -> ShowS
showsPrec :: Int -> Natural -> ShowS
$cshow :: Natural -> String
show :: Natural -> String
$cshowList :: [Natural] -> ShowS
showList :: [Natural] -> ShowS
Show)

-- |
--
-- >>> nat 3 <> nat 4
-- Natural 7
--
-- >>> nat 0 <> nat 5
-- Natural 5
instance Semigroup Natural where
  Natural Integer
x <> :: Natural -> Natural -> Natural
<> Natural Integer
y =
    Integer -> Natural
Natural (Integer
x Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
y)

-- |
--
-- >>> mempty :: Natural
-- Natural 0
instance Monoid Natural where
  mappend :: Natural -> Natural -> Natural
mappend =
    Natural -> Natural -> Natural
forall a. Semigroup a => a -> a -> a
(<>)
  mempty :: Natural
mempty =
    Integer -> Natural
Natural Integer
0

class HasNatural a where
  natural ::
    Lens'
      a
      Natural

-- |
--
-- >>> (nat 5) ^. natural
-- Natural 5
instance HasNatural Natural where
  natural :: Lens' Natural Natural
natural =
    (Natural -> f Natural) -> Natural -> f Natural
forall a. a -> a
forall {k} (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id

class AsNatural a where
  _Natural ::
    Prism'
      a
      Natural

-- |
--
-- >>> _Natural # nat 5 :: Natural
-- Natural 5
instance AsNatural Natural where
  _Natural :: Prism' Natural Natural
_Natural =
    p Natural (f Natural) -> p Natural (f Natural)
forall a. a -> a
forall {k} (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id

integralPrism ::
  (Integral a) =>
  Prism'
    a
    Natural
integralPrism :: forall a. Integral a => Prism' a Natural
integralPrism =
  (Natural -> a) -> (a -> Maybe Natural) -> Prism a a Natural Natural
forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism'
    (\(Natural Integer
n) -> Integer -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
n)
    (\a
n -> if a
n a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
0 then Maybe Natural
forall a. Maybe a
Nothing else Natural -> Maybe Natural
forall a. a -> Maybe a
Just (Integer -> Natural
Natural (a -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
n)))

-- |
--
-- >>> (5 :: Int) ^? _Natural
-- Just (Natural 5)
--
-- >>> (-1 :: Int) ^? _Natural
-- Nothing
instance AsNatural Int where
  _Natural :: Prism' Int Natural
_Natural =
    p Natural (f Natural) -> p Int (f Int)
forall a. Integral a => Prism' a Natural
Prism' Int Natural
integralPrism

-- |
--
-- >>> (42 :: Integer) ^? _Natural
-- Just (Natural 42)
--
-- >>> (-1 :: Integer) ^? _Natural
-- Nothing
instance AsNatural Integer where
  _Natural :: Prism' Integer Natural
_Natural =
    p Natural (f Natural) -> p Integer (f Integer)
forall a. Integral a => Prism' a Natural
Prism' Integer Natural
integralPrism

-- |
--
-- >>> (7 :: Word) ^? _Natural
-- Just (Natural 7)
instance AsNatural Word where
  _Natural :: Prism' Word Natural
_Natural =
    p Natural (f Natural) -> p Word (f Word)
forall a. Integral a => Prism' a Natural
Prism' Word Natural
integralPrism

-- |
--
-- >>> import Data.Functor.Identity(Identity(..))
-- >>> import Control.Applicative(Const(..))
-- >>> (Const 5 :: Const Integer Bool) ^? _Natural
-- Just (Natural 5)
instance (Integral a) => AsNatural (Const a b) where
  _Natural :: Prism' (Const a b) Natural
_Natural =
    p Natural (f Natural) -> p (Const a b) (f (Const a b))
forall a. Integral a => Prism' a Natural
Prism' (Const a b) Natural
integralPrism

-- |
--
-- >>> import Data.Functor.Identity(Identity(..))
-- >>> (Identity 5 :: Identity Integer) ^? _Natural
-- Just (Natural 5)
instance (Integral a) => AsNatural (Identity a) where
  _Natural :: Prism' (Identity a) Natural
_Natural =
    p Natural (f Natural) -> p (Identity a) (f (Identity a))
forall a. Integral a => Prism' a Natural
Prism' (Identity a) Natural
integralPrism

-- |
--
-- >>> ProductNatural (nat 3) <> ProductNatural (nat 4)
-- ProductNatural (Natural 12)
--
-- >>> mempty :: ProductNatural
-- ProductNatural (Natural 1)
newtype ProductNatural
  = ProductNatural
      Natural
  deriving (ProductNatural -> ProductNatural -> Bool
(ProductNatural -> ProductNatural -> Bool)
-> (ProductNatural -> ProductNatural -> Bool) -> Eq ProductNatural
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ProductNatural -> ProductNatural -> Bool
== :: ProductNatural -> ProductNatural -> Bool
$c/= :: ProductNatural -> ProductNatural -> Bool
/= :: ProductNatural -> ProductNatural -> Bool
Eq, Eq ProductNatural
Eq ProductNatural =>
(ProductNatural -> ProductNatural -> Ordering)
-> (ProductNatural -> ProductNatural -> Bool)
-> (ProductNatural -> ProductNatural -> Bool)
-> (ProductNatural -> ProductNatural -> Bool)
-> (ProductNatural -> ProductNatural -> Bool)
-> (ProductNatural -> ProductNatural -> ProductNatural)
-> (ProductNatural -> ProductNatural -> ProductNatural)
-> Ord ProductNatural
ProductNatural -> ProductNatural -> Bool
ProductNatural -> ProductNatural -> Ordering
ProductNatural -> ProductNatural -> ProductNatural
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
$ccompare :: ProductNatural -> ProductNatural -> Ordering
compare :: ProductNatural -> ProductNatural -> Ordering
$c< :: ProductNatural -> ProductNatural -> Bool
< :: ProductNatural -> ProductNatural -> Bool
$c<= :: ProductNatural -> ProductNatural -> Bool
<= :: ProductNatural -> ProductNatural -> Bool
$c> :: ProductNatural -> ProductNatural -> Bool
> :: ProductNatural -> ProductNatural -> Bool
$c>= :: ProductNatural -> ProductNatural -> Bool
>= :: ProductNatural -> ProductNatural -> Bool
$cmax :: ProductNatural -> ProductNatural -> ProductNatural
max :: ProductNatural -> ProductNatural -> ProductNatural
$cmin :: ProductNatural -> ProductNatural -> ProductNatural
min :: ProductNatural -> ProductNatural -> ProductNatural
Ord, Int -> ProductNatural -> ShowS
[ProductNatural] -> ShowS
ProductNatural -> String
(Int -> ProductNatural -> ShowS)
-> (ProductNatural -> String)
-> ([ProductNatural] -> ShowS)
-> Show ProductNatural
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ProductNatural -> ShowS
showsPrec :: Int -> ProductNatural -> ShowS
$cshow :: ProductNatural -> String
show :: ProductNatural -> String
$cshowList :: [ProductNatural] -> ShowS
showList :: [ProductNatural] -> ShowS
Show)

-- |
--
-- >>> ProductNatural (nat 5) ^. natural
-- Natural 5
instance HasNatural ProductNatural where
  natural :: Lens' ProductNatural Natural
natural =
    (Unwrapped ProductNatural -> f (Unwrapped ProductNatural))
-> ProductNatural -> f ProductNatural
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
Iso
  ProductNatural
  ProductNatural
  (Unwrapped ProductNatural)
  (Unwrapped ProductNatural)
_Wrapped ((Unwrapped ProductNatural -> f (Unwrapped ProductNatural))
 -> ProductNatural -> f ProductNatural)
-> ((Natural -> f Natural)
    -> Unwrapped ProductNatural -> f (Unwrapped ProductNatural))
-> (Natural -> f Natural)
-> ProductNatural
-> f ProductNatural
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Natural -> f Natural)
-> Unwrapped ProductNatural -> f (Unwrapped ProductNatural)
(Natural -> f Natural) -> Natural -> f Natural
forall a. HasNatural a => Lens' a Natural
Lens' Natural Natural
natural

-- |
--
-- >>> ProductNatural (nat 5) ^? _Natural
-- Just (Natural 5)
instance AsNatural ProductNatural where
  _Natural :: Prism' ProductNatural Natural
_Natural =
    p (Unwrapped ProductNatural) (f (Unwrapped ProductNatural))
-> p ProductNatural (f ProductNatural)
p Natural (f Natural) -> p ProductNatural (f ProductNatural)
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
Iso
  ProductNatural
  ProductNatural
  (Unwrapped ProductNatural)
  (Unwrapped ProductNatural)
_Wrapped (p Natural (f Natural) -> p ProductNatural (f ProductNatural))
-> (p Natural (f Natural) -> p Natural (f Natural))
-> p Natural (f Natural)
-> p ProductNatural (f ProductNatural)
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. p Natural (f Natural) -> p Natural (f Natural)
forall a. AsNatural a => Prism' a Natural
Prism' Natural Natural
_Natural

instance
  (ProductNatural ~ a) =>
  Rewrapped ProductNatural a

-- |
--
-- >>> ProductNatural (nat 5) ^. _Wrapped'
-- Natural 5
instance Wrapped ProductNatural where
  type Unwrapped ProductNatural = Natural
  _Wrapped' :: Iso
  ProductNatural
  ProductNatural
  (Unwrapped ProductNatural)
  (Unwrapped ProductNatural)
_Wrapped' =
    (ProductNatural -> Natural)
-> (Natural -> ProductNatural)
-> Iso ProductNatural ProductNatural Natural Natural
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso
      (\(ProductNatural Natural
x) -> Natural
x)
      Natural -> ProductNatural
ProductNatural

-- |
--
-- >>> ProductNatural (nat 3) <> ProductNatural (nat 4)
-- ProductNatural (Natural 12)
instance Semigroup ProductNatural where
  ProductNatural (Natural Integer
x) <> :: ProductNatural -> ProductNatural -> ProductNatural
<> ProductNatural (Natural Integer
y) =
    Natural -> ProductNatural
ProductNatural (Integer -> Natural
Natural (Integer
x Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
y))

-- |
--
-- >>> mempty :: ProductNatural
-- ProductNatural (Natural 1)
instance Monoid ProductNatural where
  mappend :: ProductNatural -> ProductNatural -> ProductNatural
mappend =
    ProductNatural -> ProductNatural -> ProductNatural
forall a. Semigroup a => a -> a -> a
(<>)
  mempty :: ProductNatural
mempty =
    Natural -> ProductNatural
ProductNatural (Integer -> Natural
Natural Integer
1)

-- |
--
-- >>> MaxNatural (nat 3) <> MaxNatural (nat 7)
-- MaxNatural (Natural 7)
newtype MaxNatural
  = MaxNatural
      Natural
  deriving (MaxNatural -> MaxNatural -> Bool
(MaxNatural -> MaxNatural -> Bool)
-> (MaxNatural -> MaxNatural -> Bool) -> Eq MaxNatural
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: MaxNatural -> MaxNatural -> Bool
== :: MaxNatural -> MaxNatural -> Bool
$c/= :: MaxNatural -> MaxNatural -> Bool
/= :: MaxNatural -> MaxNatural -> Bool
Eq, Eq MaxNatural
Eq MaxNatural =>
(MaxNatural -> MaxNatural -> Ordering)
-> (MaxNatural -> MaxNatural -> Bool)
-> (MaxNatural -> MaxNatural -> Bool)
-> (MaxNatural -> MaxNatural -> Bool)
-> (MaxNatural -> MaxNatural -> Bool)
-> (MaxNatural -> MaxNatural -> MaxNatural)
-> (MaxNatural -> MaxNatural -> MaxNatural)
-> Ord MaxNatural
MaxNatural -> MaxNatural -> Bool
MaxNatural -> MaxNatural -> Ordering
MaxNatural -> MaxNatural -> MaxNatural
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
$ccompare :: MaxNatural -> MaxNatural -> Ordering
compare :: MaxNatural -> MaxNatural -> Ordering
$c< :: MaxNatural -> MaxNatural -> Bool
< :: MaxNatural -> MaxNatural -> Bool
$c<= :: MaxNatural -> MaxNatural -> Bool
<= :: MaxNatural -> MaxNatural -> Bool
$c> :: MaxNatural -> MaxNatural -> Bool
> :: MaxNatural -> MaxNatural -> Bool
$c>= :: MaxNatural -> MaxNatural -> Bool
>= :: MaxNatural -> MaxNatural -> Bool
$cmax :: MaxNatural -> MaxNatural -> MaxNatural
max :: MaxNatural -> MaxNatural -> MaxNatural
$cmin :: MaxNatural -> MaxNatural -> MaxNatural
min :: MaxNatural -> MaxNatural -> MaxNatural
Ord, Int -> MaxNatural -> ShowS
[MaxNatural] -> ShowS
MaxNatural -> String
(Int -> MaxNatural -> ShowS)
-> (MaxNatural -> String)
-> ([MaxNatural] -> ShowS)
-> Show MaxNatural
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> MaxNatural -> ShowS
showsPrec :: Int -> MaxNatural -> ShowS
$cshow :: MaxNatural -> String
show :: MaxNatural -> String
$cshowList :: [MaxNatural] -> ShowS
showList :: [MaxNatural] -> ShowS
Show)

-- |
--
-- >>> MaxNatural (nat 7) ^. natural
-- Natural 7
instance HasNatural MaxNatural where
  natural :: Lens' MaxNatural Natural
natural =
    (Unwrapped MaxNatural -> f (Unwrapped MaxNatural))
-> MaxNatural -> f MaxNatural
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
Iso
  MaxNatural MaxNatural (Unwrapped MaxNatural) (Unwrapped MaxNatural)
_Wrapped ((Unwrapped MaxNatural -> f (Unwrapped MaxNatural))
 -> MaxNatural -> f MaxNatural)
-> ((Natural -> f Natural)
    -> Unwrapped MaxNatural -> f (Unwrapped MaxNatural))
-> (Natural -> f Natural)
-> MaxNatural
-> f MaxNatural
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Natural -> f Natural)
-> Unwrapped MaxNatural -> f (Unwrapped MaxNatural)
(Natural -> f Natural) -> Natural -> f Natural
forall a. HasNatural a => Lens' a Natural
Lens' Natural Natural
natural

-- |
--
-- >>> MaxNatural (nat 7) ^? _Natural
-- Just (Natural 7)
instance AsNatural MaxNatural where
  _Natural :: Prism' MaxNatural Natural
_Natural =
    p (Unwrapped MaxNatural) (f (Unwrapped MaxNatural))
-> p MaxNatural (f MaxNatural)
p Natural (f Natural) -> p MaxNatural (f MaxNatural)
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
Iso
  MaxNatural MaxNatural (Unwrapped MaxNatural) (Unwrapped MaxNatural)
_Wrapped (p Natural (f Natural) -> p MaxNatural (f MaxNatural))
-> (p Natural (f Natural) -> p Natural (f Natural))
-> p Natural (f Natural)
-> p MaxNatural (f MaxNatural)
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. p Natural (f Natural) -> p Natural (f Natural)
forall a. AsNatural a => Prism' a Natural
Prism' Natural Natural
_Natural

instance
  (MaxNatural ~ a) =>
  Rewrapped MaxNatural a

-- |
--
-- >>> MaxNatural (nat 7) ^. _Wrapped'
-- Natural 7
instance Wrapped MaxNatural where
  type Unwrapped MaxNatural = Natural
  _Wrapped' :: Iso
  MaxNatural MaxNatural (Unwrapped MaxNatural) (Unwrapped MaxNatural)
_Wrapped' =
    (MaxNatural -> Natural)
-> (Natural -> MaxNatural)
-> Iso MaxNatural MaxNatural Natural Natural
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso
      (\(MaxNatural Natural
x) -> Natural
x)
      Natural -> MaxNatural
MaxNatural

-- |
--
-- >>> MaxNatural (nat 3) <> MaxNatural (nat 7)
-- MaxNatural (Natural 7)
instance Semigroup MaxNatural where
  MaxNatural (Natural Integer
x) <> :: MaxNatural -> MaxNatural -> MaxNatural
<> MaxNatural (Natural Integer
y) =
    Natural -> MaxNatural
MaxNatural (Integer -> Natural
Natural (Integer
x Integer -> Integer -> Integer
forall a. Ord a => a -> a -> a
`max` Integer
y))

-- |
--
-- >>> MinNatural (nat 3) <> MinNatural (nat 7)
-- MinNatural (Natural 3)
newtype MinNatural
  = MinNatural
      Natural
  deriving (MinNatural -> MinNatural -> Bool
(MinNatural -> MinNatural -> Bool)
-> (MinNatural -> MinNatural -> Bool) -> Eq MinNatural
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: MinNatural -> MinNatural -> Bool
== :: MinNatural -> MinNatural -> Bool
$c/= :: MinNatural -> MinNatural -> Bool
/= :: MinNatural -> MinNatural -> Bool
Eq, Eq MinNatural
Eq MinNatural =>
(MinNatural -> MinNatural -> Ordering)
-> (MinNatural -> MinNatural -> Bool)
-> (MinNatural -> MinNatural -> Bool)
-> (MinNatural -> MinNatural -> Bool)
-> (MinNatural -> MinNatural -> Bool)
-> (MinNatural -> MinNatural -> MinNatural)
-> (MinNatural -> MinNatural -> MinNatural)
-> Ord MinNatural
MinNatural -> MinNatural -> Bool
MinNatural -> MinNatural -> Ordering
MinNatural -> MinNatural -> MinNatural
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
$ccompare :: MinNatural -> MinNatural -> Ordering
compare :: MinNatural -> MinNatural -> Ordering
$c< :: MinNatural -> MinNatural -> Bool
< :: MinNatural -> MinNatural -> Bool
$c<= :: MinNatural -> MinNatural -> Bool
<= :: MinNatural -> MinNatural -> Bool
$c> :: MinNatural -> MinNatural -> Bool
> :: MinNatural -> MinNatural -> Bool
$c>= :: MinNatural -> MinNatural -> Bool
>= :: MinNatural -> MinNatural -> Bool
$cmax :: MinNatural -> MinNatural -> MinNatural
max :: MinNatural -> MinNatural -> MinNatural
$cmin :: MinNatural -> MinNatural -> MinNatural
min :: MinNatural -> MinNatural -> MinNatural
Ord, Int -> MinNatural -> ShowS
[MinNatural] -> ShowS
MinNatural -> String
(Int -> MinNatural -> ShowS)
-> (MinNatural -> String)
-> ([MinNatural] -> ShowS)
-> Show MinNatural
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> MinNatural -> ShowS
showsPrec :: Int -> MinNatural -> ShowS
$cshow :: MinNatural -> String
show :: MinNatural -> String
$cshowList :: [MinNatural] -> ShowS
showList :: [MinNatural] -> ShowS
Show)

-- |
--
-- >>> MinNatural (nat 3) ^. natural
-- Natural 3
instance HasNatural MinNatural where
  natural :: Lens' MinNatural Natural
natural =
    (Unwrapped MinNatural -> f (Unwrapped MinNatural))
-> MinNatural -> f MinNatural
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
Iso
  MinNatural MinNatural (Unwrapped MinNatural) (Unwrapped MinNatural)
_Wrapped ((Unwrapped MinNatural -> f (Unwrapped MinNatural))
 -> MinNatural -> f MinNatural)
-> ((Natural -> f Natural)
    -> Unwrapped MinNatural -> f (Unwrapped MinNatural))
-> (Natural -> f Natural)
-> MinNatural
-> f MinNatural
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Natural -> f Natural)
-> Unwrapped MinNatural -> f (Unwrapped MinNatural)
(Natural -> f Natural) -> Natural -> f Natural
forall a. HasNatural a => Lens' a Natural
Lens' Natural Natural
natural

-- |
--
-- >>> MinNatural (nat 3) ^? _Natural
-- Just (Natural 3)
instance AsNatural MinNatural where
  _Natural :: Prism' MinNatural Natural
_Natural =
    p (Unwrapped MinNatural) (f (Unwrapped MinNatural))
-> p MinNatural (f MinNatural)
p Natural (f Natural) -> p MinNatural (f MinNatural)
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
Iso
  MinNatural MinNatural (Unwrapped MinNatural) (Unwrapped MinNatural)
_Wrapped (p Natural (f Natural) -> p MinNatural (f MinNatural))
-> (p Natural (f Natural) -> p Natural (f Natural))
-> p Natural (f Natural)
-> p MinNatural (f MinNatural)
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. p Natural (f Natural) -> p Natural (f Natural)
forall a. AsNatural a => Prism' a Natural
Prism' Natural Natural
_Natural

instance
  (MinNatural ~ a) =>
  Rewrapped MinNatural a

-- |
--
-- >>> MinNatural (nat 3) ^. _Wrapped'
-- Natural 3
instance Wrapped MinNatural where
  type Unwrapped MinNatural = Natural
  _Wrapped' :: Iso
  MinNatural MinNatural (Unwrapped MinNatural) (Unwrapped MinNatural)
_Wrapped' =
    (MinNatural -> Natural)
-> (Natural -> MinNatural)
-> Iso MinNatural MinNatural Natural Natural
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso
      (\(MinNatural Natural
x) -> Natural
x)
      Natural -> MinNatural
MinNatural

-- |
--
-- >>> MinNatural (nat 3) <> MinNatural (nat 7)
-- MinNatural (Natural 3)
instance Semigroup MinNatural where
  MinNatural (Natural Integer
x) <> :: MinNatural -> MinNatural -> MinNatural
<> MinNatural (Natural Integer
y) =
    Natural -> MinNatural
MinNatural (Integer -> Natural
Natural (Integer
x Integer -> Integer -> Integer
forall a. Ord a => a -> a -> a
`min` Integer
y))

-- | Serialises a 'Natural' to a JSON number.
--
-- >>> fromJSON (Number 0) :: Result Natural
-- Success (Natural 0)
--
-- >>> fromJSON (Number 42) :: Result Natural
-- Success (Natural 42)
--
-- >>> decode "42" :: Maybe Natural
-- Just (Natural 42)
--
-- >>> decode "0" :: Maybe Natural
-- Just (Natural 0)
--
-- >>> decode "-1" :: Maybe Natural
-- Nothing
instance ToJSON Natural where
  toJSON :: Natural -> Value
toJSON =
    Natural -> Value
forall a. HasNatural a => a -> Value
toJsonNatural
  toEncoding :: Natural -> Encoding
toEncoding (Natural Integer
n) =
    Integer -> Encoding
forall a. ToJSON a => a -> Encoding
toEncoding Integer
n

-- | Parses a 'Natural' from a JSON number, failing on negative values.
--
-- >>> decode "0" :: Maybe Natural
-- Just (Natural 0)
instance FromJSON Natural where
  parseJSON :: Value -> Parser Natural
parseJSON =
    Value -> Parser Natural
parseJsonNatural

-- | Serialises any value with a 'HasNatural' instance to a JSON 'Value'.
--
-- >>> toJsonNatural (nat 42)
-- Number 42.0
--
-- >>> toJsonNatural (ProductNatural (nat 12))
-- Number 12.0
--
-- >>> toJsonNatural (MaxNatural (nat 7))
-- Number 7.0
--
-- >>> toJsonNatural (MinNatural (nat 3))
-- Number 3.0
{-# SPECIALIZE toJsonNatural ::
  Natural ->
  Value
  #-}
{-# INLINE toJsonNatural #-}
toJsonNatural ::
  (HasNatural a) =>
  a ->
  Value
toJsonNatural :: forall a. HasNatural a => a -> Value
toJsonNatural a
a =
  let Natural Integer
n = a
a a -> Getting Natural a Natural -> Natural
forall s a. s -> Getting a s a -> a
^. Getting Natural a Natural
forall a. HasNatural a => Lens' a Natural
Lens' a Natural
natural
   in Integer -> Value
forall a. ToJSON a => a -> Value
toJSON Integer
n

-- | Parses a JSON value into a 'Natural', failing on negative values.
--
-- >>> parse parseJsonNatural (Number 42)
-- Success (Natural 42)
--
-- >>> parse parseJsonNatural (Number 0)
-- Success (Natural 0)
--
-- >>> parse parseJsonNatural (Number (-1))
-- Error "parse failed, Natural: expected non-negative integer"
{-# INLINE parseJsonNatural #-}
parseJsonNatural ::
  Value ->
  Parser Natural
parseJsonNatural :: Value -> Parser Natural
parseJsonNatural Value
v =
  Value -> Parser Integer
forall a. FromJSON a => Value -> Parser a
parseJSON Value
v Parser Integer -> (Integer -> Parser Natural) -> Parser Natural
forall a b. Parser a -> (a -> Parser b) -> Parser b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Integer
n ->
    if Integer
n Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
0
      then String -> Parser Natural
forall a. String -> Parser a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"parse failed, Natural: expected non-negative integer"
      else Natural -> Parser Natural
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Integer -> Natural
Natural Integer
n)

-- | Serialises a 'ProductNatural' to a JSON number.
--
-- >>> encode (ProductNatural (nat 12))
-- "12"
instance ToJSON ProductNatural where
  toJSON :: ProductNatural -> Value
toJSON =
    ProductNatural -> Value
forall a. HasNatural a => a -> Value
toJsonNatural
  toEncoding :: ProductNatural -> Encoding
toEncoding (ProductNatural Natural
n) =
    Natural -> Encoding
forall a. ToJSON a => a -> Encoding
toEncoding Natural
n

-- | Parses a 'ProductNatural' from a JSON number, failing on negative values.
--
-- >>> decode "12" :: Maybe ProductNatural
-- Just (ProductNatural (Natural 12))
--
-- >>> decode "-1" :: Maybe ProductNatural
-- Nothing
instance FromJSON ProductNatural where
  parseJSON :: Value -> Parser ProductNatural
parseJSON Value
v =
    Value -> Parser Natural
parseJsonNatural Value
v Parser Natural
-> (Natural -> Parser ProductNatural) -> Parser ProductNatural
forall a b. Parser a -> (a -> Parser b) -> Parser b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Natural
n -> ProductNatural -> Parser ProductNatural
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Natural -> ProductNatural
ProductNatural Natural
n)

-- | Serialises a 'MaxNatural' to a JSON number.
--
-- >>> encode (MaxNatural (nat 7))
-- "7"
instance ToJSON MaxNatural where
  toJSON :: MaxNatural -> Value
toJSON =
    MaxNatural -> Value
forall a. HasNatural a => a -> Value
toJsonNatural
  toEncoding :: MaxNatural -> Encoding
toEncoding (MaxNatural Natural
n) =
    Natural -> Encoding
forall a. ToJSON a => a -> Encoding
toEncoding Natural
n

-- | Parses a 'MaxNatural' from a JSON number, failing on negative values.
--
-- >>> decode "7" :: Maybe MaxNatural
-- Just (MaxNatural (Natural 7))
--
-- >>> decode "-1" :: Maybe MaxNatural
-- Nothing
instance FromJSON MaxNatural where
  parseJSON :: Value -> Parser MaxNatural
parseJSON Value
v =
    Value -> Parser Natural
parseJsonNatural Value
v Parser Natural
-> (Natural -> Parser MaxNatural) -> Parser MaxNatural
forall a b. Parser a -> (a -> Parser b) -> Parser b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Natural
n -> MaxNatural -> Parser MaxNatural
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Natural -> MaxNatural
MaxNatural Natural
n)

-- | Serialises a 'MinNatural' to a JSON number.
--
-- >>> encode (MinNatural (nat 3))
-- "3"
instance ToJSON MinNatural where
  toJSON :: MinNatural -> Value
toJSON =
    MinNatural -> Value
forall a. HasNatural a => a -> Value
toJsonNatural
  toEncoding :: MinNatural -> Encoding
toEncoding (MinNatural Natural
n) =
    Natural -> Encoding
forall a. ToJSON a => a -> Encoding
toEncoding Natural
n

-- | Parses a 'MinNatural' from a JSON number, failing on negative values.
--
-- >>> decode "3" :: Maybe MinNatural
-- Just (MinNatural (Natural 3))
--
-- >>> decode "-1" :: Maybe MinNatural
-- Nothing
instance FromJSON MinNatural where
  parseJSON :: Value -> Parser MinNatural
parseJSON Value
v =
    Value -> Parser Natural
parseJsonNatural Value
v Parser Natural
-> (Natural -> Parser MinNatural) -> Parser MinNatural
forall a b. Parser a -> (a -> Parser b) -> Parser b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Natural
n -> MinNatural -> Parser MinNatural
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Natural -> MinNatural
MinNatural Natural
n)

-- | Prism matching zero.
--
-- >>> zero # ()
-- Natural 0
--
-- >>> nat 0 ^? zero
-- Just ()
--
-- >>> nat 3 ^? zero
-- Nothing
zero ::
  Prism'
    Natural
    ()
zero :: Prism' Natural ()
zero =
  (() -> Natural) -> (Natural -> Maybe ()) -> Prism' Natural ()
forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism'
    (\() -> Integer -> Natural
Natural Integer
0)
    (\(Natural Integer
n) -> if Integer
n Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0 then () -> Maybe ()
forall a. a -> Maybe a
Just () else Maybe ()
forall a. Maybe a
Nothing)

-- | The zero natural number.
--
-- >>> zero'
-- Natural 0
zero' ::
  Natural
zero' :: Natural
zero' =
  Tagged () (Identity ()) -> Tagged Natural (Identity Natural)
Prism' Natural ()
zero (Tagged () (Identity ()) -> Tagged Natural (Identity Natural))
-> () -> Natural
forall t b. AReview t b -> b -> t
# ()

-- | Prism between a natural and its predecessor.
--
-- >>> successor # nat 0
-- Natural 1
--
-- >>> successor # nat 4
-- Natural 5
--
-- >>> nat 5 ^? successor
-- Just (Natural 4)
--
-- >>> nat 0 ^? successor
-- Nothing
successor ::
  Prism'
    Natural
    Natural
successor :: Prism' Natural Natural
successor =
  (Natural -> Natural)
-> (Natural -> Maybe Natural) -> Prism' Natural Natural
forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism'
    (\(Natural Integer
n) -> Integer -> Natural
Natural (Integer
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
1))
    (\(Natural Integer
n) -> if Integer
n Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0 then Maybe Natural
forall a. Maybe a
Nothing else Natural -> Maybe Natural
forall a. a -> Maybe a
Just (Integer -> Natural
Natural (Integer
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
1)))

-- | The successor of a natural number.
--
-- >>> successor' (nat 0)
-- Natural 1
--
-- >>> successor' (nat 4)
-- Natural 5
successor' ::
  Natural ->
  Natural
successor' :: Natural -> Natural
successor' =
  (Tagged Natural (Identity Natural)
-> Tagged Natural (Identity Natural)
Prism' Natural Natural
successor (Tagged Natural (Identity Natural)
 -> Tagged Natural (Identity Natural))
-> Natural -> Natural
forall t b. AReview t b -> b -> t
#)

-- | Add two natural numbers.
--
-- >>> plus (nat 3) (nat 4)
-- Natural 7
--
-- >>> plus (nat 0) (nat 5)
-- Natural 5
plus ::
  Natural ->
  Natural ->
  Natural
plus :: Natural -> Natural -> Natural
plus =
  Natural -> Natural -> Natural
forall a. Semigroup a => a -> a -> a
(<>)

-- | Multiply two natural numbers.
--
-- >>> multiply (nat 3) (nat 4)
-- Natural 12
--
-- >>> multiply (nat 0) (nat 5)
-- Natural 0
multiply ::
  Natural ->
  Natural ->
  Natural
multiply :: Natural -> Natural -> Natural
multiply Natural
x Natural
y =
  (Tagged
  (Unwrapped ProductNatural) (Identity (Unwrapped ProductNatural))
-> Tagged ProductNatural (Identity ProductNatural)
Tagged Natural (Identity Natural)
-> Tagged ProductNatural (Identity ProductNatural)
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
Iso
  ProductNatural
  ProductNatural
  (Unwrapped ProductNatural)
  (Unwrapped ProductNatural)
_Wrapped (Tagged Natural (Identity Natural)
 -> Tagged ProductNatural (Identity ProductNatural))
-> Natural -> ProductNatural
forall t b. AReview t b -> b -> t
# Natural
x ProductNatural -> ProductNatural -> ProductNatural
forall a. Semigroup a => a -> a -> a
<> (Tagged
  (Unwrapped ProductNatural) (Identity (Unwrapped ProductNatural))
-> Tagged ProductNatural (Identity ProductNatural)
Tagged Natural (Identity Natural)
-> Tagged ProductNatural (Identity ProductNatural)
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
Iso
  ProductNatural
  ProductNatural
  (Unwrapped ProductNatural)
  (Unwrapped ProductNatural)
_Wrapped (Tagged Natural (Identity Natural)
 -> Tagged ProductNatural (Identity ProductNatural))
-> Natural -> ProductNatural
forall t b. AReview t b -> b -> t
# Natural
y :: ProductNatural)) ProductNatural -> Getting Natural ProductNatural Natural -> Natural
forall s a. s -> Getting a s a -> a
^. (Unwrapped ProductNatural
 -> Const Natural (Unwrapped ProductNatural))
-> ProductNatural -> Const Natural ProductNatural
Getting Natural ProductNatural Natural
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
Iso
  ProductNatural
  ProductNatural
  (Unwrapped ProductNatural)
  (Unwrapped ProductNatural)
_Wrapped

-- | Raise a natural to a natural power.
--
-- >>> power (nat 2) (nat 10)
-- Natural 1024
--
-- >>> power (nat 3) (nat 0)
-- Natural 1
power ::
  Natural ->
  Natural ->
  Natural
power :: Natural -> Natural -> Natural
power (Natural Integer
x) (Natural Integer
y) =
  Integer -> Natural
Natural (Integer
x Integer -> Integer -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
y)

-- | Return the natural if the prism matches, otherwise zero.
--
-- >>> zeroOr (5 :: Integer)
-- Natural 5
--
-- >>> zeroOr (-1 :: Integer)
-- Natural 0
zeroOr ::
  (AsNatural a) =>
  a ->
  Natural
zeroOr :: forall a. AsNatural a => a -> Natural
zeroOr a
n =
  Natural -> Maybe Natural -> Natural
forall a. a -> Maybe a -> a
fromMaybe Natural
zero' (a
n a -> Getting (First Natural) a Natural -> Maybe Natural
forall s a. s -> Getting (First a) s a -> Maybe a
^? Getting (First Natural) a Natural
forall a. AsNatural a => Prism' a Natural
Prism' a Natural
_Natural)

-- | Count the elements in a foldable structure.
--
-- >>> length [1,2,3 :: Int]
-- Natural 3
--
-- >>> length ([] :: [Int])
-- Natural 0
length ::
  (Foldable f) =>
  f a ->
  Natural
length :: forall (f :: * -> *) a. Foldable f => f a -> Natural
length =
  (Natural -> a -> Natural) -> Natural -> f a -> Natural
forall b a. (b -> a -> b) -> b -> f a -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (Natural -> a -> Natural
forall a b. a -> b -> a
const (Natural -> a -> Natural)
-> (Natural -> Natural) -> Natural -> a -> Natural
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Natural -> Natural
successor') Natural
zero'

-- | Replicate a value a natural number of times.
--
-- >>> replicate (nat 3) 'x'
-- "xxx"
--
-- >>> replicate (nat 0) 'x'
-- ""
replicate ::
  Natural ->
  a ->
  [a]
replicate :: forall a. Natural -> a -> [a]
replicate Natural
n =
  Natural -> [a] -> [a]
forall a. Natural -> [a] -> [a]
take Natural
n ([a] -> [a]) -> (a -> [a]) -> a -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. a -> [a]
forall a. a -> [a]
repeat

-- | Take the first n elements.
--
-- >>> take (nat 2) [1,2,3,4,5 :: Int]
-- [1,2]
--
-- >>> take (nat 0) [1,2,3 :: Int]
-- []
--
-- >>> take (nat 5) [1,2 :: Int]
-- [1,2]
take ::
  Natural ->
  [a] ->
  [a]
take :: forall a. Natural -> [a] -> [a]
take Natural
_ [] =
  []
take Natural
n (a
h : [a]
t) =
  case Natural
n Natural -> Getting (First Natural) Natural Natural -> Maybe Natural
forall s a. s -> Getting (First a) s a -> Maybe a
^? Getting (First Natural) Natural Natural
Prism' Natural Natural
successor of
    Maybe Natural
Nothing ->
      []
    Just Natural
p ->
      a
h a -> [a] -> [a]
forall a. a -> [a] -> [a]
: Natural -> [a] -> [a]
forall a. Natural -> [a] -> [a]
take Natural
p [a]
t

-- | Drop the first n elements.
--
-- >>> drop (nat 2) [1,2,3,4,5 :: Int]
-- [3,4,5]
--
-- >>> drop (nat 0) [1,2,3 :: Int]
-- [1,2,3]
--
-- >>> drop (nat 5) [1,2 :: Int]
-- []
drop ::
  Natural ->
  [a] ->
  [a]
drop :: forall a. Natural -> [a] -> [a]
drop Natural
_ [] =
  []
drop Natural
n (a
h : [a]
t) =
  case Natural
n Natural -> Getting (First Natural) Natural Natural -> Maybe Natural
forall s a. s -> Getting (First a) s a -> Maybe a
^? Getting (First Natural) Natural Natural
Prism' Natural Natural
successor of
    Maybe Natural
Nothing ->
      a
h a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
t
    Just Natural
p ->
      Natural -> [a] -> [a]
forall a. Natural -> [a] -> [a]
drop Natural
p [a]
t

-- | Split a list at position n.
--
-- >>> splitAt (nat 2) [1,2,3,4,5 :: Int]
-- ([1,2],[3,4,5])
splitAt ::
  Natural ->
  [a] ->
  ([a], [a])
splitAt :: forall a. Natural -> [a] -> ([a], [a])
splitAt Natural
n [a]
x =
  (Natural -> [a] -> [a]
forall a. Natural -> [a] -> [a]
take Natural
n [a]
x, Natural -> [a] -> [a]
forall a. Natural -> [a] -> [a]
drop Natural
n [a]
x)

-- | Index into a list.
--
-- >>> [10,20,30 :: Int] !! nat 0
-- Just 10
--
-- >>> [10,20,30 :: Int] !! nat 2
-- Just 30
--
-- >>> [10,20,30 :: Int] !! nat 5
-- Nothing
--
-- >>> ([] :: [Int]) !! nat 0
-- Nothing
(!!) ::
  [a] ->
  Natural ->
  Maybe a
[] !! :: forall a. [a] -> Natural -> Maybe a
!! Natural
_ =
  Maybe a
forall a. Maybe a
Nothing
(a
h : [a]
t) !! Natural
n =
  case Natural
n Natural -> Getting (First Natural) Natural Natural -> Maybe Natural
forall s a. s -> Getting (First a) s a -> Maybe a
^? Getting (First Natural) Natural Natural
Prism' Natural Natural
successor of
    Maybe Natural
Nothing ->
      a -> Maybe a
forall a. a -> Maybe a
Just a
h
    Just Natural
p ->
      [a]
t [a] -> Natural -> Maybe a
forall a. [a] -> Natural -> Maybe a
!! Natural
p

-- | Find all indices where the predicate holds.
--
-- >>> findIndices (== 'a') "abacad"
-- [Natural 0,Natural 2,Natural 4]
--
-- >>> findIndices (== 'z') "abacad"
-- []
findIndices ::
  (a -> Bool) ->
  [a] ->
  [Natural]
findIndices :: forall a. (a -> Bool) -> [a] -> [Natural]
findIndices a -> Bool
p [a]
x =
  ((a, Natural) -> Natural) -> [(a, Natural)] -> [Natural]
forall a b. (a -> b) -> [a] -> [b]
map (a, Natural) -> Natural
forall a b. (a, b) -> b
snd (((a, Natural) -> Bool) -> [(a, Natural)] -> [(a, Natural)]
forall a. (a -> Bool) -> [a] -> [a]
filter (a -> Bool
p (a -> Bool) -> ((a, Natural) -> a) -> (a, Natural) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (a, Natural) -> a
forall a b. (a, b) -> a
fst) ([a] -> [Natural] -> [(a, Natural)]
forall a b. [a] -> [b] -> [(a, b)]
zip [a]
x ((Natural -> Natural) -> Natural -> [Natural]
forall a. (a -> a) -> a -> [a]
iterate Natural -> Natural
successor' Natural
zero')))

-- | Find the first index where the predicate holds.
--
-- >>> findIndex (== 'c') "abcde"
-- Just (Natural 2)
--
-- >>> findIndex (== 'z') "abcde"
-- Nothing
findIndex ::
  (a -> Bool) ->
  [a] ->
  Maybe Natural
findIndex :: forall a. (a -> Bool) -> [a] -> Maybe Natural
findIndex a -> Bool
p =
  [Natural] -> Maybe Natural
forall a. [a] -> Maybe a
listToMaybe ([Natural] -> Maybe Natural)
-> ([a] -> [Natural]) -> [a] -> Maybe Natural
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (a -> Bool) -> [a] -> [Natural]
forall a. (a -> Bool) -> [a] -> [Natural]
findIndices a -> Bool
p

-- | Find all indices of a given element.
--
-- >>> elemIndices 'a' "banana"
-- [Natural 1,Natural 3,Natural 5]
elemIndices ::
  (Eq a) =>
  a ->
  [a] ->
  [Natural]
elemIndices :: forall a. Eq a => a -> [a] -> [Natural]
elemIndices =
  (a -> Bool) -> [a] -> [Natural]
forall a. (a -> Bool) -> [a] -> [Natural]
findIndices ((a -> Bool) -> [a] -> [Natural])
-> (a -> a -> Bool) -> a -> [a] -> [Natural]
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. a -> a -> Bool
forall a. Eq a => a -> a -> Bool
(==)

-- | Find the first index of a given element.
--
-- >>> elemIndex 'n' "banana"
-- Just (Natural 2)
--
-- >>> elemIndex 'z' "banana"
-- Nothing
elemIndex ::
  (Eq a) =>
  a ->
  [a] ->
  Maybe Natural
elemIndex :: forall a. Eq a => a -> [a] -> Maybe Natural
elemIndex =
  (a -> Bool) -> [a] -> Maybe Natural
forall a. (a -> Bool) -> [a] -> Maybe Natural
findIndex ((a -> Bool) -> [a] -> Maybe Natural)
-> (a -> a -> Bool) -> a -> [a] -> Maybe Natural
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. a -> a -> Bool
forall a. Eq a => a -> a -> Bool
(==)

-- | Subtract two naturals, flooring at zero.
--
-- >>> minus (nat 5) (nat 3)
-- Natural 2
--
-- >>> minus (nat 3) (nat 5)
-- Natural 0
--
-- >>> minus (nat 3) (nat 3)
-- Natural 0
minus ::
  Natural ->
  Natural ->
  Natural
minus :: Natural -> Natural -> Natural
minus (Natural Integer
x) (Natural Integer
y) =
  Integer -> Natural
Natural (if Integer
x Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
y then Integer
0 else Integer
x Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
y)

-- | Iso between a natural and a list of units.
--
-- >>> nat 3 ^. list
-- [(),(),()]
--
-- >>> length (nat 3 ^. list)
-- Natural 3
list ::
  Iso'
    Natural
    [()]
list :: Iso' Natural [()]
list =
  (Natural -> [()]) -> ([()] -> Natural) -> Iso' Natural [()]
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso
    (Natural -> () -> [()]
forall a. Natural -> a -> [a]
`replicate` ())
    [()] -> Natural
forall (f :: * -> *) a. Foldable f => f a -> Natural
length

----

-- | A positive integer (>= 1). Semigroup is multiplication.
--
-- >>> pos 3
-- Positive 3
--
-- >>> pos 3 <> pos 4
-- Positive 12
newtype Positive
  = Positive
      Integer
  deriving (Positive -> Positive -> Bool
(Positive -> Positive -> Bool)
-> (Positive -> Positive -> Bool) -> Eq Positive
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Positive -> Positive -> Bool
== :: Positive -> Positive -> Bool
$c/= :: Positive -> Positive -> Bool
/= :: Positive -> Positive -> Bool
Eq, Eq Positive
Eq Positive =>
(Positive -> Positive -> Ordering)
-> (Positive -> Positive -> Bool)
-> (Positive -> Positive -> Bool)
-> (Positive -> Positive -> Bool)
-> (Positive -> Positive -> Bool)
-> (Positive -> Positive -> Positive)
-> (Positive -> Positive -> Positive)
-> Ord Positive
Positive -> Positive -> Bool
Positive -> Positive -> Ordering
Positive -> Positive -> Positive
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
$ccompare :: Positive -> Positive -> Ordering
compare :: Positive -> Positive -> Ordering
$c< :: Positive -> Positive -> Bool
< :: Positive -> Positive -> Bool
$c<= :: Positive -> Positive -> Bool
<= :: Positive -> Positive -> Bool
$c> :: Positive -> Positive -> Bool
> :: Positive -> Positive -> Bool
$c>= :: Positive -> Positive -> Bool
>= :: Positive -> Positive -> Bool
$cmax :: Positive -> Positive -> Positive
max :: Positive -> Positive -> Positive
$cmin :: Positive -> Positive -> Positive
min :: Positive -> Positive -> Positive
Ord, Int -> Positive -> ShowS
[Positive] -> ShowS
Positive -> String
(Int -> Positive -> ShowS)
-> (Positive -> String) -> ([Positive] -> ShowS) -> Show Positive
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Positive -> ShowS
showsPrec :: Int -> Positive -> ShowS
$cshow :: Positive -> String
show :: Positive -> String
$cshowList :: [Positive] -> ShowS
showList :: [Positive] -> ShowS
Show)

-- |
--
-- >>> pos 3 <> pos 4
-- Positive 12
instance Semigroup Positive where
  Positive Integer
x <> :: Positive -> Positive -> Positive
<> Positive Integer
y =
    Integer -> Positive
Positive (Integer
x Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
y)

class HasPositive a where
  positive ::
    Lens'
      a
      Positive

-- |
--
-- >>> pos 5 ^. positive
-- Positive 5
instance HasPositive Positive where
  positive :: Lens' Positive Positive
positive =
    (Positive -> f Positive) -> Positive -> f Positive
forall a. a -> a
forall {k} (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id

class AsPositive a where
  _Positive ::
    Prism'
      a
      Positive

-- |
--
-- >>> _Positive # pos 5 :: Positive
-- Positive 5
instance AsPositive Positive where
  _Positive :: Prism' Positive Positive
_Positive =
    p Positive (f Positive) -> p Positive (f Positive)
forall a. a -> a
forall {k} (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id

integralPrism1 ::
  (Integral a) =>
  Prism'
    a
    Positive
integralPrism1 :: forall a. Integral a => Prism' a Positive
integralPrism1 =
  (Positive -> a)
-> (a -> Maybe Positive) -> Prism a a Positive Positive
forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism'
    (\(Positive Integer
n) -> Integer -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
n)
    (\a
n -> if a
n a -> a -> Bool
forall a. Ord a => a -> a -> Bool
< a
1 then Maybe Positive
forall a. Maybe a
Nothing else Positive -> Maybe Positive
forall a. a -> Maybe a
Just (Integer -> Positive
Positive (a -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
n)))

-- |
--
-- >>> (5 :: Int) ^? _Positive
-- Just (Positive 5)
--
-- >>> (0 :: Int) ^? _Positive
-- Nothing
instance AsPositive Int where
  _Positive :: Prism' Int Positive
_Positive =
    p Positive (f Positive) -> p Int (f Int)
forall a. Integral a => Prism' a Positive
Prism' Int Positive
integralPrism1

-- |
--
-- >>> (42 :: Integer) ^? _Positive
-- Just (Positive 42)
--
-- >>> (0 :: Integer) ^? _Positive
-- Nothing
instance AsPositive Integer where
  _Positive :: Prism' Integer Positive
_Positive =
    p Positive (f Positive) -> p Integer (f Integer)
forall a. Integral a => Prism' a Positive
Prism' Integer Positive
integralPrism1

-- |
--
-- >>> (7 :: Word) ^? _Positive
-- Just (Positive 7)
--
-- >>> (0 :: Word) ^? _Positive
-- Nothing
instance AsPositive Word where
  _Positive :: Prism' Word Positive
_Positive =
    p Positive (f Positive) -> p Word (f Word)
forall a. Integral a => Prism' a Positive
Prism' Word Positive
integralPrism1

-- |
--
-- >>> import Control.Applicative(Const(..))
-- >>> (Const 5 :: Const Integer Bool) ^? _Positive
-- Just (Positive 5)
instance (Integral a) => AsPositive (Const a b) where
  _Positive :: Prism' (Const a b) Positive
_Positive =
    p Positive (f Positive) -> p (Const a b) (f (Const a b))
forall a. Integral a => Prism' a Positive
Prism' (Const a b) Positive
integralPrism1

-- |
--
-- >>> import Data.Functor.Identity(Identity(..))
-- >>> (Identity 5 :: Identity Integer) ^? _Positive
-- Just (Positive 5)
instance (Integral a) => AsPositive (Identity a) where
  _Positive :: Prism' (Identity a) Positive
_Positive =
    p Positive (f Positive) -> p (Identity a) (f (Identity a))
forall a. Integral a => Prism' a Positive
Prism' (Identity a) Positive
integralPrism1

-- |
--
-- >>> SumPositive (pos 3) <> SumPositive (pos 4)
-- SumPositive (Positive 7)
newtype SumPositive
  = SumPositive
      Positive
  deriving (SumPositive -> SumPositive -> Bool
(SumPositive -> SumPositive -> Bool)
-> (SumPositive -> SumPositive -> Bool) -> Eq SumPositive
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SumPositive -> SumPositive -> Bool
== :: SumPositive -> SumPositive -> Bool
$c/= :: SumPositive -> SumPositive -> Bool
/= :: SumPositive -> SumPositive -> Bool
Eq, Eq SumPositive
Eq SumPositive =>
(SumPositive -> SumPositive -> Ordering)
-> (SumPositive -> SumPositive -> Bool)
-> (SumPositive -> SumPositive -> Bool)
-> (SumPositive -> SumPositive -> Bool)
-> (SumPositive -> SumPositive -> Bool)
-> (SumPositive -> SumPositive -> SumPositive)
-> (SumPositive -> SumPositive -> SumPositive)
-> Ord SumPositive
SumPositive -> SumPositive -> Bool
SumPositive -> SumPositive -> Ordering
SumPositive -> SumPositive -> SumPositive
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
$ccompare :: SumPositive -> SumPositive -> Ordering
compare :: SumPositive -> SumPositive -> Ordering
$c< :: SumPositive -> SumPositive -> Bool
< :: SumPositive -> SumPositive -> Bool
$c<= :: SumPositive -> SumPositive -> Bool
<= :: SumPositive -> SumPositive -> Bool
$c> :: SumPositive -> SumPositive -> Bool
> :: SumPositive -> SumPositive -> Bool
$c>= :: SumPositive -> SumPositive -> Bool
>= :: SumPositive -> SumPositive -> Bool
$cmax :: SumPositive -> SumPositive -> SumPositive
max :: SumPositive -> SumPositive -> SumPositive
$cmin :: SumPositive -> SumPositive -> SumPositive
min :: SumPositive -> SumPositive -> SumPositive
Ord, Int -> SumPositive -> ShowS
[SumPositive] -> ShowS
SumPositive -> String
(Int -> SumPositive -> ShowS)
-> (SumPositive -> String)
-> ([SumPositive] -> ShowS)
-> Show SumPositive
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SumPositive -> ShowS
showsPrec :: Int -> SumPositive -> ShowS
$cshow :: SumPositive -> String
show :: SumPositive -> String
$cshowList :: [SumPositive] -> ShowS
showList :: [SumPositive] -> ShowS
Show)

-- |
--
-- >>> SumPositive (pos 5) ^. positive
-- Positive 5
instance HasPositive SumPositive where
  positive :: Lens' SumPositive Positive
positive =
    (Unwrapped SumPositive -> f (Unwrapped SumPositive))
-> SumPositive -> f SumPositive
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
Iso
  SumPositive
  SumPositive
  (Unwrapped SumPositive)
  (Unwrapped SumPositive)
_Wrapped ((Unwrapped SumPositive -> f (Unwrapped SumPositive))
 -> SumPositive -> f SumPositive)
-> ((Positive -> f Positive)
    -> Unwrapped SumPositive -> f (Unwrapped SumPositive))
-> (Positive -> f Positive)
-> SumPositive
-> f SumPositive
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Positive -> f Positive)
-> Unwrapped SumPositive -> f (Unwrapped SumPositive)
(Positive -> f Positive) -> Positive -> f Positive
forall a. HasPositive a => Lens' a Positive
Lens' Positive Positive
positive

-- |
--
-- >>> SumPositive (pos 5) ^? _Positive
-- Just (Positive 5)
instance AsPositive SumPositive where
  _Positive :: Prism' SumPositive Positive
_Positive =
    p (Unwrapped SumPositive) (f (Unwrapped SumPositive))
-> p SumPositive (f SumPositive)
p Positive (f Positive) -> p SumPositive (f SumPositive)
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
Iso
  SumPositive
  SumPositive
  (Unwrapped SumPositive)
  (Unwrapped SumPositive)
_Wrapped (p Positive (f Positive) -> p SumPositive (f SumPositive))
-> (p Positive (f Positive) -> p Positive (f Positive))
-> p Positive (f Positive)
-> p SumPositive (f SumPositive)
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. p Positive (f Positive) -> p Positive (f Positive)
forall a. AsPositive a => Prism' a Positive
Prism' Positive Positive
_Positive

instance
  (SumPositive ~ a) =>
  Rewrapped SumPositive a

-- |
--
-- >>> SumPositive (pos 5) ^. _Wrapped'
-- Positive 5
instance Wrapped SumPositive where
  type Unwrapped SumPositive = Positive
  _Wrapped' :: Iso
  SumPositive
  SumPositive
  (Unwrapped SumPositive)
  (Unwrapped SumPositive)
_Wrapped' =
    (SumPositive -> Positive)
-> (Positive -> SumPositive)
-> Iso SumPositive SumPositive Positive Positive
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso
      (\(SumPositive Positive
x) -> Positive
x)
      Positive -> SumPositive
SumPositive

-- |
--
-- >>> SumPositive (pos 3) <> SumPositive (pos 4)
-- SumPositive (Positive 7)
instance Semigroup SumPositive where
  SumPositive (Positive Integer
x) <> :: SumPositive -> SumPositive -> SumPositive
<> SumPositive (Positive Integer
y) =
    Positive -> SumPositive
SumPositive (Integer -> Positive
Positive (Integer
x Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
y))

-- |
--
-- >>> MaxPositive (pos 3) <> MaxPositive (pos 7)
-- MaxPositive (Positive 7)
newtype MaxPositive
  = MaxPositive
      Positive
  deriving (MaxPositive -> MaxPositive -> Bool
(MaxPositive -> MaxPositive -> Bool)
-> (MaxPositive -> MaxPositive -> Bool) -> Eq MaxPositive
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: MaxPositive -> MaxPositive -> Bool
== :: MaxPositive -> MaxPositive -> Bool
$c/= :: MaxPositive -> MaxPositive -> Bool
/= :: MaxPositive -> MaxPositive -> Bool
Eq, Eq MaxPositive
Eq MaxPositive =>
(MaxPositive -> MaxPositive -> Ordering)
-> (MaxPositive -> MaxPositive -> Bool)
-> (MaxPositive -> MaxPositive -> Bool)
-> (MaxPositive -> MaxPositive -> Bool)
-> (MaxPositive -> MaxPositive -> Bool)
-> (MaxPositive -> MaxPositive -> MaxPositive)
-> (MaxPositive -> MaxPositive -> MaxPositive)
-> Ord MaxPositive
MaxPositive -> MaxPositive -> Bool
MaxPositive -> MaxPositive -> Ordering
MaxPositive -> MaxPositive -> MaxPositive
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
$ccompare :: MaxPositive -> MaxPositive -> Ordering
compare :: MaxPositive -> MaxPositive -> Ordering
$c< :: MaxPositive -> MaxPositive -> Bool
< :: MaxPositive -> MaxPositive -> Bool
$c<= :: MaxPositive -> MaxPositive -> Bool
<= :: MaxPositive -> MaxPositive -> Bool
$c> :: MaxPositive -> MaxPositive -> Bool
> :: MaxPositive -> MaxPositive -> Bool
$c>= :: MaxPositive -> MaxPositive -> Bool
>= :: MaxPositive -> MaxPositive -> Bool
$cmax :: MaxPositive -> MaxPositive -> MaxPositive
max :: MaxPositive -> MaxPositive -> MaxPositive
$cmin :: MaxPositive -> MaxPositive -> MaxPositive
min :: MaxPositive -> MaxPositive -> MaxPositive
Ord, Int -> MaxPositive -> ShowS
[MaxPositive] -> ShowS
MaxPositive -> String
(Int -> MaxPositive -> ShowS)
-> (MaxPositive -> String)
-> ([MaxPositive] -> ShowS)
-> Show MaxPositive
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> MaxPositive -> ShowS
showsPrec :: Int -> MaxPositive -> ShowS
$cshow :: MaxPositive -> String
show :: MaxPositive -> String
$cshowList :: [MaxPositive] -> ShowS
showList :: [MaxPositive] -> ShowS
Show)

-- |
--
-- >>> MaxPositive (pos 7) ^. positive
-- Positive 7
instance HasPositive MaxPositive where
  positive :: Lens' MaxPositive Positive
positive =
    (Unwrapped MaxPositive -> f (Unwrapped MaxPositive))
-> MaxPositive -> f MaxPositive
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
Iso
  MaxPositive
  MaxPositive
  (Unwrapped MaxPositive)
  (Unwrapped MaxPositive)
_Wrapped ((Unwrapped MaxPositive -> f (Unwrapped MaxPositive))
 -> MaxPositive -> f MaxPositive)
-> ((Positive -> f Positive)
    -> Unwrapped MaxPositive -> f (Unwrapped MaxPositive))
-> (Positive -> f Positive)
-> MaxPositive
-> f MaxPositive
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Positive -> f Positive)
-> Unwrapped MaxPositive -> f (Unwrapped MaxPositive)
(Positive -> f Positive) -> Positive -> f Positive
forall a. HasPositive a => Lens' a Positive
Lens' Positive Positive
positive

-- |
--
-- >>> MaxPositive (pos 7) ^? _Positive
-- Just (Positive 7)
instance AsPositive MaxPositive where
  _Positive :: Prism' MaxPositive Positive
_Positive =
    p (Unwrapped MaxPositive) (f (Unwrapped MaxPositive))
-> p MaxPositive (f MaxPositive)
p Positive (f Positive) -> p MaxPositive (f MaxPositive)
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
Iso
  MaxPositive
  MaxPositive
  (Unwrapped MaxPositive)
  (Unwrapped MaxPositive)
_Wrapped (p Positive (f Positive) -> p MaxPositive (f MaxPositive))
-> (p Positive (f Positive) -> p Positive (f Positive))
-> p Positive (f Positive)
-> p MaxPositive (f MaxPositive)
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. p Positive (f Positive) -> p Positive (f Positive)
forall a. AsPositive a => Prism' a Positive
Prism' Positive Positive
_Positive

instance
  (MaxPositive ~ a) =>
  Rewrapped MaxPositive a

-- |
--
-- >>> MaxPositive (pos 7) ^. _Wrapped'
-- Positive 7
instance Wrapped MaxPositive where
  type Unwrapped MaxPositive = Positive
  _Wrapped' :: Iso
  MaxPositive
  MaxPositive
  (Unwrapped MaxPositive)
  (Unwrapped MaxPositive)
_Wrapped' =
    (MaxPositive -> Positive)
-> (Positive -> MaxPositive)
-> Iso MaxPositive MaxPositive Positive Positive
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso
      (\(MaxPositive Positive
x) -> Positive
x)
      Positive -> MaxPositive
MaxPositive

-- |
--
-- >>> MaxPositive (pos 3) <> MaxPositive (pos 7)
-- MaxPositive (Positive 7)
instance Semigroup MaxPositive where
  MaxPositive (Positive Integer
x) <> :: MaxPositive -> MaxPositive -> MaxPositive
<> MaxPositive (Positive Integer
y) =
    Positive -> MaxPositive
MaxPositive (Integer -> Positive
Positive (Integer
x Integer -> Integer -> Integer
forall a. Ord a => a -> a -> a
`max` Integer
y))

-- |
--
-- >>> MinPositive (pos 3) <> MinPositive (pos 7)
-- MinPositive (Positive 3)
newtype MinPositive
  = MinPositive
      Positive
  deriving (MinPositive -> MinPositive -> Bool
(MinPositive -> MinPositive -> Bool)
-> (MinPositive -> MinPositive -> Bool) -> Eq MinPositive
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: MinPositive -> MinPositive -> Bool
== :: MinPositive -> MinPositive -> Bool
$c/= :: MinPositive -> MinPositive -> Bool
/= :: MinPositive -> MinPositive -> Bool
Eq, Eq MinPositive
Eq MinPositive =>
(MinPositive -> MinPositive -> Ordering)
-> (MinPositive -> MinPositive -> Bool)
-> (MinPositive -> MinPositive -> Bool)
-> (MinPositive -> MinPositive -> Bool)
-> (MinPositive -> MinPositive -> Bool)
-> (MinPositive -> MinPositive -> MinPositive)
-> (MinPositive -> MinPositive -> MinPositive)
-> Ord MinPositive
MinPositive -> MinPositive -> Bool
MinPositive -> MinPositive -> Ordering
MinPositive -> MinPositive -> MinPositive
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
$ccompare :: MinPositive -> MinPositive -> Ordering
compare :: MinPositive -> MinPositive -> Ordering
$c< :: MinPositive -> MinPositive -> Bool
< :: MinPositive -> MinPositive -> Bool
$c<= :: MinPositive -> MinPositive -> Bool
<= :: MinPositive -> MinPositive -> Bool
$c> :: MinPositive -> MinPositive -> Bool
> :: MinPositive -> MinPositive -> Bool
$c>= :: MinPositive -> MinPositive -> Bool
>= :: MinPositive -> MinPositive -> Bool
$cmax :: MinPositive -> MinPositive -> MinPositive
max :: MinPositive -> MinPositive -> MinPositive
$cmin :: MinPositive -> MinPositive -> MinPositive
min :: MinPositive -> MinPositive -> MinPositive
Ord, Int -> MinPositive -> ShowS
[MinPositive] -> ShowS
MinPositive -> String
(Int -> MinPositive -> ShowS)
-> (MinPositive -> String)
-> ([MinPositive] -> ShowS)
-> Show MinPositive
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> MinPositive -> ShowS
showsPrec :: Int -> MinPositive -> ShowS
$cshow :: MinPositive -> String
show :: MinPositive -> String
$cshowList :: [MinPositive] -> ShowS
showList :: [MinPositive] -> ShowS
Show)

-- |
--
-- >>> MinPositive (pos 3) ^. positive
-- Positive 3
instance HasPositive MinPositive where
  positive :: Lens' MinPositive Positive
positive =
    (Unwrapped MinPositive -> f (Unwrapped MinPositive))
-> MinPositive -> f MinPositive
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
Iso
  MinPositive
  MinPositive
  (Unwrapped MinPositive)
  (Unwrapped MinPositive)
_Wrapped ((Unwrapped MinPositive -> f (Unwrapped MinPositive))
 -> MinPositive -> f MinPositive)
-> ((Positive -> f Positive)
    -> Unwrapped MinPositive -> f (Unwrapped MinPositive))
-> (Positive -> f Positive)
-> MinPositive
-> f MinPositive
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Positive -> f Positive)
-> Unwrapped MinPositive -> f (Unwrapped MinPositive)
(Positive -> f Positive) -> Positive -> f Positive
forall a. HasPositive a => Lens' a Positive
Lens' Positive Positive
positive

-- |
--
-- >>> MinPositive (pos 3) ^? _Positive
-- Just (Positive 3)
instance AsPositive MinPositive where
  _Positive :: Prism' MinPositive Positive
_Positive =
    p (Unwrapped MinPositive) (f (Unwrapped MinPositive))
-> p MinPositive (f MinPositive)
p Positive (f Positive) -> p MinPositive (f MinPositive)
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
Iso
  MinPositive
  MinPositive
  (Unwrapped MinPositive)
  (Unwrapped MinPositive)
_Wrapped (p Positive (f Positive) -> p MinPositive (f MinPositive))
-> (p Positive (f Positive) -> p Positive (f Positive))
-> p Positive (f Positive)
-> p MinPositive (f MinPositive)
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. p Positive (f Positive) -> p Positive (f Positive)
forall a. AsPositive a => Prism' a Positive
Prism' Positive Positive
_Positive

instance
  (MinPositive ~ a) =>
  Rewrapped MinPositive a

-- |
--
-- >>> MinPositive (pos 3) ^. _Wrapped'
-- Positive 3
instance Wrapped MinPositive where
  type Unwrapped MinPositive = Positive
  _Wrapped' :: Iso
  MinPositive
  MinPositive
  (Unwrapped MinPositive)
  (Unwrapped MinPositive)
_Wrapped' =
    (MinPositive -> Positive)
-> (Positive -> MinPositive)
-> Iso MinPositive MinPositive Positive Positive
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso
      (\(MinPositive Positive
x) -> Positive
x)
      Positive -> MinPositive
MinPositive

-- |
--
-- >>> MinPositive (pos 3) <> MinPositive (pos 7)
-- MinPositive (Positive 3)
instance Semigroup MinPositive where
  MinPositive (Positive Integer
x) <> :: MinPositive -> MinPositive -> MinPositive
<> MinPositive (Positive Integer
y) =
    Positive -> MinPositive
MinPositive (Integer -> Positive
Positive (Integer
x Integer -> Integer -> Integer
forall a. Ord a => a -> a -> a
`min` Integer
y))

-- | Serialises a 'Positive' to a JSON number.
--
-- >>> fromJSON (Number 1) :: Result Positive
-- Success (Positive 1)
--
-- >>> fromJSON (Number 42) :: Result Positive
-- Success (Positive 42)
--
-- >>> decode "42" :: Maybe Positive
-- Just (Positive 42)
--
-- >>> decode "1" :: Maybe Positive
-- Just (Positive 1)
--
-- >>> decode "0" :: Maybe Positive
-- Nothing
--
-- >>> decode "-1" :: Maybe Positive
-- Nothing
instance ToJSON Positive where
  toJSON :: Positive -> Value
toJSON =
    Positive -> Value
forall a. HasPositive a => a -> Value
toJsonPositive
  toEncoding :: Positive -> Encoding
toEncoding (Positive Integer
n) =
    Integer -> Encoding
forall a. ToJSON a => a -> Encoding
toEncoding Integer
n

-- | Parses a 'Positive' from a JSON number, failing on non-positive values.
--
-- >>> decode "1" :: Maybe Positive
-- Just (Positive 1)
instance FromJSON Positive where
  parseJSON :: Value -> Parser Positive
parseJSON =
    Value -> Parser Positive
parseJsonPositive

-- | Serialises any value with a 'HasPositive' instance to a JSON 'Value'.
--
-- >>> toJsonPositive (pos 42)
-- Number 42.0
--
-- >>> toJsonPositive (SumPositive (pos 7))
-- Number 7.0
--
-- >>> toJsonPositive (MaxPositive (pos 7))
-- Number 7.0
--
-- >>> toJsonPositive (MinPositive (pos 3))
-- Number 3.0
{-# SPECIALIZE toJsonPositive ::
  Positive ->
  Value
  #-}
{-# INLINE toJsonPositive #-}
toJsonPositive ::
  (HasPositive a) =>
  a ->
  Value
toJsonPositive :: forall a. HasPositive a => a -> Value
toJsonPositive a
a =
  let Positive Integer
n = a
a a -> Getting Positive a Positive -> Positive
forall s a. s -> Getting a s a -> a
^. Getting Positive a Positive
forall a. HasPositive a => Lens' a Positive
Lens' a Positive
positive
   in Integer -> Value
forall a. ToJSON a => a -> Value
toJSON Integer
n

-- | Parses a JSON value into a 'Positive', failing on non-positive values.
--
-- >>> parse parseJsonPositive (Number 42)
-- Success (Positive 42)
--
-- >>> parse parseJsonPositive (Number 1)
-- Success (Positive 1)
--
-- >>> parse parseJsonPositive (Number 0)
-- Error "parse failed, Positive: expected positive integer"
--
-- >>> parse parseJsonPositive (Number (-1))
-- Error "parse failed, Positive: expected positive integer"
{-# INLINE parseJsonPositive #-}
parseJsonPositive ::
  Value ->
  Parser Positive
parseJsonPositive :: Value -> Parser Positive
parseJsonPositive Value
v =
  Value -> Parser Integer
forall a. FromJSON a => Value -> Parser a
parseJSON Value
v Parser Integer -> (Integer -> Parser Positive) -> Parser Positive
forall a b. Parser a -> (a -> Parser b) -> Parser b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Integer
n ->
    if Integer
n Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
1
      then String -> Parser Positive
forall a. String -> Parser a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"parse failed, Positive: expected positive integer"
      else Positive -> Parser Positive
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Integer -> Positive
Positive Integer
n)

-- | Serialises a 'SumPositive' to a JSON number.
--
-- >>> encode (SumPositive (pos 7))
-- "7"
instance ToJSON SumPositive where
  toJSON :: SumPositive -> Value
toJSON =
    SumPositive -> Value
forall a. HasPositive a => a -> Value
toJsonPositive
  toEncoding :: SumPositive -> Encoding
toEncoding (SumPositive Positive
n) =
    Positive -> Encoding
forall a. ToJSON a => a -> Encoding
toEncoding Positive
n

-- | Parses a 'SumPositive' from a JSON number, failing on non-positive values.
--
-- >>> decode "7" :: Maybe SumPositive
-- Just (SumPositive (Positive 7))
--
-- >>> decode "0" :: Maybe SumPositive
-- Nothing
instance FromJSON SumPositive where
  parseJSON :: Value -> Parser SumPositive
parseJSON Value
v =
    Value -> Parser Positive
parseJsonPositive Value
v Parser Positive
-> (Positive -> Parser SumPositive) -> Parser SumPositive
forall a b. Parser a -> (a -> Parser b) -> Parser b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Positive
n -> SumPositive -> Parser SumPositive
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Positive -> SumPositive
SumPositive Positive
n)

-- | Serialises a 'MaxPositive' to a JSON number.
--
-- >>> encode (MaxPositive (pos 7))
-- "7"
instance ToJSON MaxPositive where
  toJSON :: MaxPositive -> Value
toJSON =
    MaxPositive -> Value
forall a. HasPositive a => a -> Value
toJsonPositive
  toEncoding :: MaxPositive -> Encoding
toEncoding (MaxPositive Positive
n) =
    Positive -> Encoding
forall a. ToJSON a => a -> Encoding
toEncoding Positive
n

-- | Parses a 'MaxPositive' from a JSON number, failing on non-positive values.
--
-- >>> decode "7" :: Maybe MaxPositive
-- Just (MaxPositive (Positive 7))
--
-- >>> decode "0" :: Maybe MaxPositive
-- Nothing
instance FromJSON MaxPositive where
  parseJSON :: Value -> Parser MaxPositive
parseJSON Value
v =
    Value -> Parser Positive
parseJsonPositive Value
v Parser Positive
-> (Positive -> Parser MaxPositive) -> Parser MaxPositive
forall a b. Parser a -> (a -> Parser b) -> Parser b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Positive
n -> MaxPositive -> Parser MaxPositive
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Positive -> MaxPositive
MaxPositive Positive
n)

-- | Serialises a 'MinPositive' to a JSON number.
--
-- >>> encode (MinPositive (pos 3))
-- "3"
instance ToJSON MinPositive where
  toJSON :: MinPositive -> Value
toJSON =
    MinPositive -> Value
forall a. HasPositive a => a -> Value
toJsonPositive
  toEncoding :: MinPositive -> Encoding
toEncoding (MinPositive Positive
n) =
    Positive -> Encoding
forall a. ToJSON a => a -> Encoding
toEncoding Positive
n

-- | Parses a 'MinPositive' from a JSON number, failing on non-positive values.
--
-- >>> decode "3" :: Maybe MinPositive
-- Just (MinPositive (Positive 3))
--
-- >>> decode "0" :: Maybe MinPositive
-- Nothing
instance FromJSON MinPositive where
  parseJSON :: Value -> Parser MinPositive
parseJSON Value
v =
    Value -> Parser Positive
parseJsonPositive Value
v Parser Positive
-> (Positive -> Parser MinPositive) -> Parser MinPositive
forall a b. Parser a -> (a -> Parser b) -> Parser b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Positive
n -> MinPositive -> Parser MinPositive
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Positive -> MinPositive
MinPositive Positive
n)

-- | Iso between a natural and maybe a positive.
--
-- >>> nat 5 ^. naturalPositive
-- Just (Positive 5)
--
-- >>> nat 0 ^. naturalPositive
-- Nothing
naturalPositive ::
  Iso' Natural (Maybe Positive)
naturalPositive :: Iso' Natural (Maybe Positive)
naturalPositive =
  (Natural -> Maybe Positive)
-> (Maybe Positive -> Natural) -> Iso' Natural (Maybe Positive)
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso
    ( \(Natural Integer
n) ->
        if Integer
n Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0 then Maybe Positive
forall a. Maybe a
Nothing else Positive -> Maybe Positive
forall a. a -> Maybe a
Just (Integer -> Positive
Positive Integer
n)
    )
    ( \Maybe Positive
x ->
        Integer -> Natural
Natural
          ( case Maybe Positive
x of
              Maybe Positive
Nothing ->
                Integer
0
              Just (Positive Integer
n) ->
                Integer
n
          )
    )

-- |
--
-- >>> nat 5 ^? _Positive
-- Just (Positive 5)
--
-- >>> nat 0 ^? _Positive
-- Nothing
instance AsPositive Natural where
  _Positive :: Prism' Natural Positive
_Positive =
    (Positive -> Natural)
-> (Natural -> Maybe Positive) -> Prism' Natural Positive
forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism'
      (\(Positive Integer
n) -> Integer -> Natural
Natural Integer
n)
      (\(Natural Integer
n) -> if Integer
n Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0 then Maybe Positive
forall a. Maybe a
Nothing else Positive -> Maybe Positive
forall a. a -> Maybe a
Just (Integer -> Positive
Positive Integer
n))

-- | Prism matching one.
--
-- >>> one # ()
-- Positive 1
--
-- >>> pos 1 ^? one
-- Just ()
--
-- >>> pos 3 ^? one
-- Nothing
one ::
  Prism'
    Positive
    ()
one :: Prism' Positive ()
one =
  (() -> Positive) -> (Positive -> Maybe ()) -> Prism' Positive ()
forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism'
    (\() -> Integer -> Positive
Positive Integer
1)
    (\(Positive Integer
n) -> if Integer
n Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
1 then () -> Maybe ()
forall a. a -> Maybe a
Just () else Maybe ()
forall a. Maybe a
Nothing)

-- | The positive number one.
--
-- >>> one'
-- Positive 1
one' ::
  Positive
one' :: Positive
one' =
  Tagged () (Identity ()) -> Tagged Positive (Identity Positive)
Prism' Positive ()
one (Tagged () (Identity ()) -> Tagged Positive (Identity Positive))
-> () -> Positive
forall t b. AReview t b -> b -> t
# ()

-- | Prism between a positive and its predecessor.
--
-- >>> successor1 # pos 1
-- Positive 2
--
-- >>> successor1 # pos 4
-- Positive 5
--
-- >>> pos 5 ^? successor1
-- Just (Positive 4)
--
-- >>> pos 1 ^? successor1
-- Nothing
successor1 ::
  Prism'
    Positive
    Positive
successor1 :: Prism' Positive Positive
successor1 =
  (Positive -> Positive)
-> (Positive -> Maybe Positive) -> Prism' Positive Positive
forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism'
    (\(Positive Integer
n) -> Integer -> Positive
Positive (Integer
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
1))
    (\(Positive Integer
n) -> if Integer
n Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
1 then Maybe Positive
forall a. Maybe a
Nothing else Positive -> Maybe Positive
forall a. a -> Maybe a
Just (Integer -> Positive
Positive (Integer
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
1)))

-- | The successor of a positive number.
--
-- >>> successor1' (pos 1)
-- Positive 2
--
-- >>> successor1' (pos 4)
-- Positive 5
successor1' ::
  Positive ->
  Positive
successor1' :: Positive -> Positive
successor1' =
  (Tagged Positive (Identity Positive)
-> Tagged Positive (Identity Positive)
Prism' Positive Positive
successor1 (Tagged Positive (Identity Positive)
 -> Tagged Positive (Identity Positive))
-> Positive -> Positive
forall t b. AReview t b -> b -> t
#)

-- | Iso between natural and positive (n <-> n+1).
--
-- >>> nat 0 ^. successorW
-- Positive 1
--
-- >>> nat 4 ^. successorW
-- Positive 5
--
-- >>> successorW # pos 1
-- Natural 0
--
-- >>> successorW # pos 5
-- Natural 4
successorW ::
  Iso'
    Natural
    Positive
successorW :: Iso' Natural Positive
successorW =
  (Natural -> Positive)
-> (Positive -> Natural) -> Iso' Natural Positive
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso
    (\(Natural Integer
n) -> Integer -> Positive
Positive (Integer
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
1))
    (\(Positive Integer
n) -> Integer -> Natural
Natural (Integer
n Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
1))

-- | Add two positive numbers.
--
-- >>> plus1 (pos 3) (pos 4)
-- Positive 7
plus1 ::
  Positive ->
  Positive ->
  Positive
plus1 :: Positive -> Positive -> Positive
plus1 Positive
x Positive
y =
  (Tagged (Unwrapped SumPositive) (Identity (Unwrapped SumPositive))
-> Tagged SumPositive (Identity SumPositive)
Tagged Positive (Identity Positive)
-> Tagged SumPositive (Identity SumPositive)
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
Iso
  SumPositive
  SumPositive
  (Unwrapped SumPositive)
  (Unwrapped SumPositive)
_Wrapped (Tagged Positive (Identity Positive)
 -> Tagged SumPositive (Identity SumPositive))
-> Positive -> SumPositive
forall t b. AReview t b -> b -> t
# Positive
x SumPositive -> SumPositive -> SumPositive
forall a. Semigroup a => a -> a -> a
<> (Tagged (Unwrapped SumPositive) (Identity (Unwrapped SumPositive))
-> Tagged SumPositive (Identity SumPositive)
Tagged Positive (Identity Positive)
-> Tagged SumPositive (Identity SumPositive)
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
Iso
  SumPositive
  SumPositive
  (Unwrapped SumPositive)
  (Unwrapped SumPositive)
_Wrapped (Tagged Positive (Identity Positive)
 -> Tagged SumPositive (Identity SumPositive))
-> Positive -> SumPositive
forall t b. AReview t b -> b -> t
# Positive
y :: SumPositive)) SumPositive -> Getting Positive SumPositive Positive -> Positive
forall s a. s -> Getting a s a -> a
^. (Unwrapped SumPositive -> Const Positive (Unwrapped SumPositive))
-> SumPositive -> Const Positive SumPositive
Getting Positive SumPositive Positive
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
Iso
  SumPositive
  SumPositive
  (Unwrapped SumPositive)
  (Unwrapped SumPositive)
_Wrapped

-- | Multiply two positive numbers.
--
-- >>> multiply1 (pos 3) (pos 4)
-- Positive 12
multiply1 ::
  Positive ->
  Positive ->
  Positive
multiply1 :: Positive -> Positive -> Positive
multiply1 =
  Positive -> Positive -> Positive
forall a. Semigroup a => a -> a -> a
(<>)

-- | Raise a positive to a positive power.
--
-- >>> power1 (pos 2) (pos 10)
-- Positive 1024
--
-- >>> power1 (pos 3) (pos 2)
-- Positive 9
power1 ::
  Positive ->
  Positive ->
  Positive
power1 :: Positive -> Positive -> Positive
power1 (Positive Integer
x) (Positive Integer
y) =
  Integer -> Positive
Positive (Integer
x Integer -> Integer -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^ Integer
y)

-- | Return the positive if the prism matches, otherwise one.
--
-- >>> oneOr (5 :: Integer)
-- Positive 5
--
-- >>> oneOr (0 :: Integer)
-- Positive 1
oneOr ::
  (AsPositive a) =>
  a ->
  Positive
oneOr :: forall a. AsPositive a => a -> Positive
oneOr a
n =
  Positive -> Maybe Positive -> Positive
forall a. a -> Maybe a -> a
fromMaybe Positive
one' (a
n a -> Getting (First Positive) a Positive -> Maybe Positive
forall s a. s -> Getting (First a) s a -> Maybe a
^? Getting (First Positive) a Positive
forall a. AsPositive a => Prism' a Positive
Prism' a Positive
_Positive)

-- | Count the elements in a non-empty foldable.
--
-- >>> length1 ('a' :| "bc")
-- Positive 3
--
-- >>> length1 ('x' :| "")
-- Positive 1
length1 ::
  (Foldable1 f) =>
  f a ->
  Positive
length1 :: forall (f :: * -> *) a. Foldable1 f => f a -> Positive
length1 f a
x =
  (a -> SumPositive) -> f a -> SumPositive
forall m a. Semigroup m => (a -> m) -> f a -> m
forall (t :: * -> *) m a.
(Foldable1 t, Semigroup m) =>
(a -> m) -> t a -> m
foldMap1 (SumPositive -> a -> SumPositive
forall a b. a -> b -> a
const (Positive -> SumPositive
SumPositive Positive
one')) f a
x SumPositive -> Getting Positive SumPositive Positive -> Positive
forall s a. s -> Getting a s a -> a
^. (Unwrapped SumPositive -> Const Positive (Unwrapped SumPositive))
-> SumPositive -> Const Positive SumPositive
Getting Positive SumPositive Positive
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
Iso
  SumPositive
  SumPositive
  (Unwrapped SumPositive)
  (Unwrapped SumPositive)
_Wrapped

-- | Replicate a value a positive number of times.
--
-- >>> replicate1 (pos 3) 'x'
-- 'x' :| "xx"
--
-- >>> replicate1 (pos 1) 'y'
-- 'y' :| ""
replicate1 ::
  Positive ->
  a ->
  NonEmpty a
replicate1 :: forall a. Positive -> a -> NonEmpty a
replicate1 Positive
n a
a =
  Positive -> NonEmpty a -> NonEmpty a
forall a. Positive -> NonEmpty a -> NonEmpty a
take1 Positive
n (a
a a -> [a] -> NonEmpty a
forall a. a -> [a] -> NonEmpty a
:| a -> [a]
forall a. a -> [a]
repeat a
a)

-- | Take the first n elements from a non-empty list.
--
-- >>> take1 (pos 2) (1 :| [2,3,4,5 :: Int])
-- 1 :| [2]
--
-- >>> take1 (pos 1) (1 :| [2,3 :: Int])
-- 1 :| []
take1 ::
  Positive ->
  NonEmpty a ->
  NonEmpty a
take1 :: forall a. Positive -> NonEmpty a -> NonEmpty a
take1 Positive
n (a
h :| [a]
t) =
  a
h a -> [a] -> NonEmpty a
forall a. a -> [a] -> NonEmpty a
:| Natural -> [a] -> [a]
forall a. Natural -> [a] -> [a]
take (Tagged Positive (Identity Positive)
-> Tagged Natural (Identity Natural)
Iso' Natural Positive
successorW (Tagged Positive (Identity Positive)
 -> Tagged Natural (Identity Natural))
-> Positive -> Natural
forall t b. AReview t b -> b -> t
# Positive
n) [a]
t

-- | Drop the first n elements from a non-empty list.
--
-- >>> drop1 (pos 2) (1 :| [2,3,4,5 :: Int])
-- [3,4,5]
--
-- >>> drop1 (pos 1) (1 :| [2,3 :: Int])
-- [2,3]
drop1 ::
  Positive ->
  NonEmpty a ->
  [a]
drop1 :: forall a. Positive -> NonEmpty a -> [a]
drop1 Positive
n (a
_ :| [a]
t) =
  Natural -> [a] -> [a]
forall a. Natural -> [a] -> [a]
drop (Tagged Positive (Identity Positive)
-> Tagged Natural (Identity Natural)
Iso' Natural Positive
successorW (Tagged Positive (Identity Positive)
 -> Tagged Natural (Identity Natural))
-> Positive -> Natural
forall t b. AReview t b -> b -> t
# Positive
n) [a]
t

-- | Split a non-empty list at position n.
--
-- >>> splitAt1 (pos 2) (1 :| [2,3,4,5 :: Int])
-- (1 :| [2],[3,4,5])
splitAt1 ::
  Positive ->
  NonEmpty a ->
  (NonEmpty a, [a])
splitAt1 :: forall a. Positive -> NonEmpty a -> (NonEmpty a, [a])
splitAt1 Positive
n NonEmpty a
x =
  (Positive -> NonEmpty a -> NonEmpty a
forall a. Positive -> NonEmpty a -> NonEmpty a
take1 Positive
n NonEmpty a
x, Positive -> NonEmpty a -> [a]
forall a. Positive -> NonEmpty a -> [a]
drop1 Positive
n NonEmpty a
x)

-- | Index into a non-empty list (1-based).
--
-- >>> (10 :| [20,30 :: Int]) !!! pos 1
-- Just 10
--
-- >>> (10 :| [20,30 :: Int]) !!! pos 3
-- Just 30
--
-- >>> (10 :| [20,30 :: Int]) !!! pos 5
-- Nothing
(!!!) ::
  NonEmpty a ->
  Positive ->
  Maybe a
(a
h :| [a]
t) !!! :: forall a. NonEmpty a -> Positive -> Maybe a
!!! Positive
n =
  (a
h a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
t) [a] -> Natural -> Maybe a
forall a. [a] -> Natural -> Maybe a
!! (Tagged Positive (Identity Positive)
-> Tagged Natural (Identity Natural)
Iso' Natural Positive
successorW (Tagged Positive (Identity Positive)
 -> Tagged Natural (Identity Natural))
-> Positive -> Natural
forall t b. AReview t b -> b -> t
# Positive
n)

-- | Find all 1-based indices where the predicate holds.
--
-- >>> findIndices1 (== 'a') ('a' :| "baca")
-- [Positive 1,Positive 3,Positive 5]
findIndices1 ::
  (a -> Bool) ->
  NonEmpty a ->
  [Positive]
findIndices1 :: forall a. (a -> Bool) -> NonEmpty a -> [Positive]
findIndices1 a -> Bool
p NonEmpty a
x =
  ((a, Positive) -> Positive) -> [(a, Positive)] -> [Positive]
forall a b. (a -> b) -> [a] -> [b]
map (a, Positive) -> Positive
forall a b. (a, b) -> b
snd (((a, Positive) -> Bool)
-> NonEmpty (a, Positive) -> [(a, Positive)]
forall a. (a -> Bool) -> NonEmpty a -> [a]
NonEmpty.filter (a -> Bool
p (a -> Bool) -> ((a, Positive) -> a) -> (a, Positive) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (a, Positive) -> a
forall a b. (a, b) -> a
fst) (NonEmpty a -> NonEmpty Positive -> NonEmpty (a, Positive)
forall a b. NonEmpty a -> NonEmpty b -> NonEmpty (a, b)
NonEmpty.zip NonEmpty a
x ((Positive -> Positive) -> Positive -> NonEmpty Positive
forall a. (a -> a) -> a -> NonEmpty a
NonEmpty.iterate Positive -> Positive
successor1' Positive
one')))

-- | Find the first 1-based index where the predicate holds.
--
-- >>> findIndex1 (== 'c') ('a' :| "bcde")
-- Just (Positive 3)
--
-- >>> findIndex1 (== 'z') ('a' :| "bcde")
-- Nothing
findIndex1 ::
  (a -> Bool) ->
  NonEmpty a ->
  Maybe Positive
findIndex1 :: forall a. (a -> Bool) -> NonEmpty a -> Maybe Positive
findIndex1 a -> Bool
p =
  [Positive] -> Maybe Positive
forall a. [a] -> Maybe a
listToMaybe ([Positive] -> Maybe Positive)
-> (NonEmpty a -> [Positive]) -> NonEmpty a -> Maybe Positive
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (a -> Bool) -> NonEmpty a -> [Positive]
forall a. (a -> Bool) -> NonEmpty a -> [Positive]
findIndices1 a -> Bool
p

-- | Find all 1-based indices of a given element.
--
-- >>> elemIndices1 'a' ('b' :| "anana")
-- [Positive 2,Positive 4,Positive 6]
elemIndices1 ::
  (Eq a) =>
  a ->
  NonEmpty a ->
  [Positive]
elemIndices1 :: forall a. Eq a => a -> NonEmpty a -> [Positive]
elemIndices1 =
  (a -> Bool) -> NonEmpty a -> [Positive]
forall a. (a -> Bool) -> NonEmpty a -> [Positive]
findIndices1 ((a -> Bool) -> NonEmpty a -> [Positive])
-> (a -> a -> Bool) -> a -> NonEmpty a -> [Positive]
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. a -> a -> Bool
forall a. Eq a => a -> a -> Bool
(==)

-- | Find the first 1-based index of a given element.
--
-- >>> elemIndex1 'n' ('b' :| "anana")
-- Just (Positive 3)
--
-- >>> elemIndex1 'z' ('b' :| "anana")
-- Nothing
elemIndex1 ::
  (Eq a) =>
  a ->
  NonEmpty a ->
  Maybe Positive
elemIndex1 :: forall a. Eq a => a -> NonEmpty a -> Maybe Positive
elemIndex1 =
  (a -> Bool) -> NonEmpty a -> Maybe Positive
forall a. (a -> Bool) -> NonEmpty a -> Maybe Positive
findIndex1 ((a -> Bool) -> NonEmpty a -> Maybe Positive)
-> (a -> a -> Bool) -> a -> NonEmpty a -> Maybe Positive
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. a -> a -> Bool
forall a. Eq a => a -> a -> Bool
(==)

-- | Subtract two positives, flooring at one.
--
-- >>> minus1 (pos 5) (pos 3)
-- Positive 2
--
-- >>> minus1 (pos 3) (pos 5)
-- Positive 1
--
-- >>> minus1 (pos 3) (pos 3)
-- Positive 1
minus1 ::
  Positive ->
  Positive ->
  Positive
minus1 :: Positive -> Positive -> Positive
minus1 (Positive Integer
x) (Positive Integer
y) =
  Integer -> Positive
Positive (if Integer
x Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
y then Integer
1 else Integer
x Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
y)

-- | Iso between a positive and a non-empty list of units.
--
-- >>> pos 3 ^. list1
-- () :| [(),()]
--
-- >>> length1 (pos 3 ^. list1)
-- Positive 3
list1 ::
  Iso'
    Positive
    (NonEmpty ())
list1 :: Iso' Positive (NonEmpty ())
list1 =
  (Positive -> NonEmpty ())
-> (NonEmpty () -> Positive) -> Iso' Positive (NonEmpty ())
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso
    (Positive -> () -> NonEmpty ()
forall a. Positive -> a -> NonEmpty a
`replicate1` ())
    NonEmpty () -> Positive
forall (f :: * -> *) a. Foldable1 f => f a -> Positive
length1

-- | Convert natural to positive by adding one.
--
-- >>> plusone (nat 0)
-- Positive 1
--
-- >>> plusone (nat 4)
-- Positive 5
plusone ::
  Natural ->
  Positive
plusone :: Natural -> Positive
plusone =
  (Natural -> Getting Positive Natural Positive -> Positive
forall s a. s -> Getting a s a -> a
^. Getting Positive Natural Positive
Iso' Natural Positive
successorW)

-- | Convert positive to natural by subtracting one.
--
-- >>> minusone (pos 1)
-- Natural 0
--
-- >>> minusone (pos 5)
-- Natural 4
minusone ::
  Positive ->
  Natural
minusone :: Positive -> Natural
minusone =
  (Tagged Positive (Identity Positive)
-> Tagged Natural (Identity Natural)
Iso' Natural Positive
successorW (Tagged Positive (Identity Positive)
 -> Tagged Natural (Identity Natural))
-> Positive -> Natural
forall t b. AReview t b -> b -> t
#)

----

-- | A non-zero integer. 'True' for positive, 'False' for negative.
-- The 'Positive' gives the absolute value.
--
-- >>> NotZero True (pos 3)
-- NotZero True (Positive 3)
--
-- >>> NotZero False (pos 7)
-- NotZero False (Positive 7)
data NotZero
  = NotZero
      Bool
      Positive
  deriving (NotZero -> NotZero -> Bool
(NotZero -> NotZero -> Bool)
-> (NotZero -> NotZero -> Bool) -> Eq NotZero
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: NotZero -> NotZero -> Bool
== :: NotZero -> NotZero -> Bool
$c/= :: NotZero -> NotZero -> Bool
/= :: NotZero -> NotZero -> Bool
Eq, Int -> NotZero -> ShowS
[NotZero] -> ShowS
NotZero -> String
(Int -> NotZero -> ShowS)
-> (NotZero -> String) -> ([NotZero] -> ShowS) -> Show NotZero
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> NotZero -> ShowS
showsPrec :: Int -> NotZero -> ShowS
$cshow :: NotZero -> String
show :: NotZero -> String
$cshowList :: [NotZero] -> ShowS
showList :: [NotZero] -> ShowS
Show)

-- |
--
-- >>> compare (NotZero True (pos 3)) (NotZero True (pos 5))
-- LT
--
-- >>> compare (NotZero False (pos 3)) (NotZero False (pos 5))
-- GT
--
-- >>> compare (NotZero False (pos 1)) (NotZero True (pos 1))
-- LT
--
-- >>> compare (NotZero True (pos 1)) (NotZero False (pos 1))
-- GT
instance Ord NotZero where
  compare :: NotZero -> NotZero -> Ordering
compare (NotZero Bool
False (Positive Integer
x)) (NotZero Bool
False (Positive Integer
y)) = Integer -> Integer -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Integer
y Integer
x
  compare (NotZero Bool
True (Positive Integer
x)) (NotZero Bool
True (Positive Integer
y)) = Integer -> Integer -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Integer
x Integer
y
  compare (NotZero Bool
False Positive
_) (NotZero Bool
True Positive
_) = Integer -> Integer -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Integer
0 :: Integer) (Integer
1 :: Integer)
  compare (NotZero Bool
True Positive
_) (NotZero Bool
False Positive
_) = Integer -> Integer -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (Integer
1 :: Integer) (Integer
0 :: Integer)

-- | Semigroup under addition. Note: this is partial if the result would be zero.
-- Use 'plusNZ' for a total version.
--
-- >>> NotZero True (pos 3) <> NotZero True (pos 4)
-- NotZero True (Positive 7)
--
-- >>> NotZero False (pos 3) <> NotZero False (pos 4)
-- NotZero False (Positive 7)
--
-- >>> NotZero True (pos 5) <> NotZero False (pos 3)
-- NotZero True (Positive 2)
--
-- >>> NotZero False (pos 5) <> NotZero True (pos 3)
-- NotZero False (Positive 2)
instance Semigroup NotZero where
  NotZero Bool
s1 (Positive Integer
x) <> :: NotZero -> NotZero -> NotZero
<> NotZero Bool
s2 (Positive Integer
y) =
    case (Bool
s1, Bool
s2) of
      (Bool
True, Bool
True) -> Bool -> Positive -> NotZero
NotZero Bool
True (Integer -> Positive
Positive (Integer
x Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
y))
      (Bool
False, Bool
False) -> Bool -> Positive -> NotZero
NotZero Bool
False (Integer -> Positive
Positive (Integer
x Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
y))
      (Bool
True, Bool
False)
        | Integer
x Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
y -> Bool -> Positive -> NotZero
NotZero Bool
False (Integer -> Positive
Positive (Integer
y Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
x))
        | Bool
True -> Bool -> Positive -> NotZero
NotZero Bool
True (Integer -> Positive
Positive (Integer
x Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
y))
      (Bool
False, Bool
True)
        | Integer
y Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
x -> Bool -> Positive -> NotZero
NotZero Bool
False (Integer -> Positive
Positive (Integer
x Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
y))
        | Bool
True -> Bool -> Positive -> NotZero
NotZero Bool
True (Integer -> Positive
Positive (Integer
y Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
x))

class HasNotZero a where
  notZero ::
    Lens'
      a
      NotZero

-- |
--
-- >>> NotZero True (pos 5) ^. notZero
-- NotZero True (Positive 5)
instance HasNotZero NotZero where
  notZero :: Lens' NotZero NotZero
notZero =
    (NotZero -> f NotZero) -> NotZero -> f NotZero
forall a. a -> a
forall {k} (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id

-- |
--
-- >>> (7 :: Integer) ^? _NotZero
-- Just (NotZero True (Positive 7))
--
-- >>> (-3 :: Integer) ^? _NotZero
-- Just (NotZero False (Positive 3))
--
-- >>> (0 :: Integer) ^? _NotZero
-- Nothing
class AsNotZero a where
  _NotZero ::
    Prism'
      a
      NotZero

-- |
--
-- >>> _NotZero # NotZero True (pos 5) :: NotZero
-- NotZero True (Positive 5)
instance AsNotZero NotZero where
  _NotZero :: Prism' NotZero NotZero
_NotZero =
    p NotZero (f NotZero) -> p NotZero (f NotZero)
forall a. a -> a
forall {k} (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id

integralPrismNZ ::
  (Integral a) =>
  Prism'
    a
    NotZero
integralPrismNZ :: forall a. Integral a => Prism' a NotZero
integralPrismNZ =
  (NotZero -> a) -> (a -> Maybe NotZero) -> Prism a a NotZero NotZero
forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism'
    (\(NotZero Bool
s (Positive Integer
n)) -> Integer -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (if Bool
s then Integer
n else Integer -> Integer
forall a. Num a => a -> a
negate Integer
n))
    ( \a
n ->
        let i :: Integer
i = a -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
n :: Integer
         in if Integer
i Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0
              then Maybe NotZero
forall a. Maybe a
Nothing
              else NotZero -> Maybe NotZero
forall a. a -> Maybe a
Just (Bool -> Positive -> NotZero
NotZero (Integer
i Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> Integer
0) (Integer -> Positive
Positive (Integer -> Integer
forall a. Num a => a -> a
abs Integer
i)))
    )
  where
    > :: a -> a -> Bool
(>) a
a a
b = Bool -> Bool
not (a
a a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
b) Bool -> Bool -> Bool
&& Bool -> Bool
not (a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
b)

-- |
--
-- >>> (5 :: Int) ^? _NotZero
-- Just (NotZero True (Positive 5))
--
-- >>> (-5 :: Int) ^? _NotZero
-- Just (NotZero False (Positive 5))
--
-- >>> (0 :: Int) ^? _NotZero
-- Nothing
instance AsNotZero Int where
  _NotZero :: Prism' Int NotZero
_NotZero =
    p NotZero (f NotZero) -> p Int (f Int)
forall a. Integral a => Prism' a NotZero
Prism' Int NotZero
integralPrismNZ

-- |
--
-- >>> (42 :: Integer) ^? _NotZero
-- Just (NotZero True (Positive 42))
--
-- >>> (-42 :: Integer) ^? _NotZero
-- Just (NotZero False (Positive 42))
--
-- >>> (0 :: Integer) ^? _NotZero
-- Nothing
instance AsNotZero Integer where
  _NotZero :: Prism' Integer NotZero
_NotZero =
    p NotZero (f NotZero) -> p Integer (f Integer)
forall a. Integral a => Prism' a NotZero
Prism' Integer NotZero
integralPrismNZ

-- |
--
-- >>> (1 :: Word) ^? _NotZero
-- Just (NotZero True (Positive 1))
--
-- >>> (0 :: Word) ^? _NotZero
-- Nothing
instance AsNotZero Word where
  _NotZero :: Prism' Word NotZero
_NotZero =
    p NotZero (f NotZero) -> p Word (f Word)
forall a. Integral a => Prism' a NotZero
Prism' Word NotZero
integralPrismNZ

-- |
--
-- >>> import Control.Applicative(Const(..))
-- >>> (Const 5 :: Const Integer Bool) ^? _NotZero
-- Just (NotZero True (Positive 5))
instance (Integral a) => AsNotZero (Const a b) where
  _NotZero :: Prism' (Const a b) NotZero
_NotZero =
    p NotZero (f NotZero) -> p (Const a b) (f (Const a b))
forall a. Integral a => Prism' a NotZero
Prism' (Const a b) NotZero
integralPrismNZ

-- |
--
-- >>> import Data.Functor.Identity(Identity(..))
-- >>> (Identity (-3) :: Identity Integer) ^? _NotZero
-- Just (NotZero False (Positive 3))
instance (Integral a) => AsNotZero (Identity a) where
  _NotZero :: Prism' (Identity a) NotZero
_NotZero =
    p NotZero (f NotZero) -> p (Identity a) (f (Identity a))
forall a. Integral a => Prism' a NotZero
Prism' (Identity a) NotZero
integralPrismNZ

-- |
--
-- >>> SumNotZero (NotZero True (pos 3)) <> SumNotZero (NotZero True (pos 4))
-- SumNotZero (NotZero True (Positive 7))
newtype SumNotZero
  = SumNotZero
      NotZero
  deriving (SumNotZero -> SumNotZero -> Bool
(SumNotZero -> SumNotZero -> Bool)
-> (SumNotZero -> SumNotZero -> Bool) -> Eq SumNotZero
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: SumNotZero -> SumNotZero -> Bool
== :: SumNotZero -> SumNotZero -> Bool
$c/= :: SumNotZero -> SumNotZero -> Bool
/= :: SumNotZero -> SumNotZero -> Bool
Eq, Eq SumNotZero
Eq SumNotZero =>
(SumNotZero -> SumNotZero -> Ordering)
-> (SumNotZero -> SumNotZero -> Bool)
-> (SumNotZero -> SumNotZero -> Bool)
-> (SumNotZero -> SumNotZero -> Bool)
-> (SumNotZero -> SumNotZero -> Bool)
-> (SumNotZero -> SumNotZero -> SumNotZero)
-> (SumNotZero -> SumNotZero -> SumNotZero)
-> Ord SumNotZero
SumNotZero -> SumNotZero -> Bool
SumNotZero -> SumNotZero -> Ordering
SumNotZero -> SumNotZero -> SumNotZero
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
$ccompare :: SumNotZero -> SumNotZero -> Ordering
compare :: SumNotZero -> SumNotZero -> Ordering
$c< :: SumNotZero -> SumNotZero -> Bool
< :: SumNotZero -> SumNotZero -> Bool
$c<= :: SumNotZero -> SumNotZero -> Bool
<= :: SumNotZero -> SumNotZero -> Bool
$c> :: SumNotZero -> SumNotZero -> Bool
> :: SumNotZero -> SumNotZero -> Bool
$c>= :: SumNotZero -> SumNotZero -> Bool
>= :: SumNotZero -> SumNotZero -> Bool
$cmax :: SumNotZero -> SumNotZero -> SumNotZero
max :: SumNotZero -> SumNotZero -> SumNotZero
$cmin :: SumNotZero -> SumNotZero -> SumNotZero
min :: SumNotZero -> SumNotZero -> SumNotZero
Ord, Int -> SumNotZero -> ShowS
[SumNotZero] -> ShowS
SumNotZero -> String
(Int -> SumNotZero -> ShowS)
-> (SumNotZero -> String)
-> ([SumNotZero] -> ShowS)
-> Show SumNotZero
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> SumNotZero -> ShowS
showsPrec :: Int -> SumNotZero -> ShowS
$cshow :: SumNotZero -> String
show :: SumNotZero -> String
$cshowList :: [SumNotZero] -> ShowS
showList :: [SumNotZero] -> ShowS
Show)

-- |
--
-- >>> SumNotZero (NotZero True (pos 5)) ^. notZero
-- NotZero True (Positive 5)
instance HasNotZero SumNotZero where
  notZero :: Lens' SumNotZero NotZero
notZero =
    (Unwrapped SumNotZero -> f (Unwrapped SumNotZero))
-> SumNotZero -> f SumNotZero
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
Iso
  SumNotZero SumNotZero (Unwrapped SumNotZero) (Unwrapped SumNotZero)
_Wrapped ((Unwrapped SumNotZero -> f (Unwrapped SumNotZero))
 -> SumNotZero -> f SumNotZero)
-> ((NotZero -> f NotZero)
    -> Unwrapped SumNotZero -> f (Unwrapped SumNotZero))
-> (NotZero -> f NotZero)
-> SumNotZero
-> f SumNotZero
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (NotZero -> f NotZero)
-> Unwrapped SumNotZero -> f (Unwrapped SumNotZero)
(NotZero -> f NotZero) -> NotZero -> f NotZero
forall a. HasNotZero a => Lens' a NotZero
Lens' NotZero NotZero
notZero

-- |
--
-- >>> SumNotZero (NotZero True (pos 5)) ^? _NotZero
-- Just (NotZero True (Positive 5))
instance AsNotZero SumNotZero where
  _NotZero :: Prism' SumNotZero NotZero
_NotZero =
    p (Unwrapped SumNotZero) (f (Unwrapped SumNotZero))
-> p SumNotZero (f SumNotZero)
p NotZero (f NotZero) -> p SumNotZero (f SumNotZero)
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
Iso
  SumNotZero SumNotZero (Unwrapped SumNotZero) (Unwrapped SumNotZero)
_Wrapped (p NotZero (f NotZero) -> p SumNotZero (f SumNotZero))
-> (p NotZero (f NotZero) -> p NotZero (f NotZero))
-> p NotZero (f NotZero)
-> p SumNotZero (f SumNotZero)
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. p NotZero (f NotZero) -> p NotZero (f NotZero)
forall a. AsNotZero a => Prism' a NotZero
Prism' NotZero NotZero
_NotZero

instance
  (SumNotZero ~ a) =>
  Rewrapped SumNotZero a

-- |
--
-- >>> SumNotZero (NotZero True (pos 5)) ^. _Wrapped'
-- NotZero True (Positive 5)
instance Wrapped SumNotZero where
  type Unwrapped SumNotZero = NotZero
  _Wrapped' :: Iso
  SumNotZero SumNotZero (Unwrapped SumNotZero) (Unwrapped SumNotZero)
_Wrapped' =
    (SumNotZero -> NotZero)
-> (NotZero -> SumNotZero)
-> Iso SumNotZero SumNotZero NotZero NotZero
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso
      (\(SumNotZero NotZero
x) -> NotZero
x)
      NotZero -> SumNotZero
SumNotZero

-- |
--
-- >>> SumNotZero (NotZero True (pos 3)) <> SumNotZero (NotZero True (pos 4))
-- SumNotZero (NotZero True (Positive 7))
instance Semigroup SumNotZero where
  SumNotZero NotZero
x <> :: SumNotZero -> SumNotZero -> SumNotZero
<> SumNotZero NotZero
y =
    NotZero -> SumNotZero
SumNotZero (NotZero
x NotZero -> NotZero -> NotZero
forall a. Semigroup a => a -> a -> a
<> NotZero
y)

-- |
--
-- >>> MaxNotZero (NotZero True (pos 3)) <> MaxNotZero (NotZero True (pos 7))
-- MaxNotZero (NotZero True (Positive 7))
--
-- >>> MaxNotZero (NotZero False (pos 3)) <> MaxNotZero (NotZero True (pos 1))
-- MaxNotZero (NotZero True (Positive 1))
newtype MaxNotZero
  = MaxNotZero
      NotZero
  deriving (MaxNotZero -> MaxNotZero -> Bool
(MaxNotZero -> MaxNotZero -> Bool)
-> (MaxNotZero -> MaxNotZero -> Bool) -> Eq MaxNotZero
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: MaxNotZero -> MaxNotZero -> Bool
== :: MaxNotZero -> MaxNotZero -> Bool
$c/= :: MaxNotZero -> MaxNotZero -> Bool
/= :: MaxNotZero -> MaxNotZero -> Bool
Eq, Eq MaxNotZero
Eq MaxNotZero =>
(MaxNotZero -> MaxNotZero -> Ordering)
-> (MaxNotZero -> MaxNotZero -> Bool)
-> (MaxNotZero -> MaxNotZero -> Bool)
-> (MaxNotZero -> MaxNotZero -> Bool)
-> (MaxNotZero -> MaxNotZero -> Bool)
-> (MaxNotZero -> MaxNotZero -> MaxNotZero)
-> (MaxNotZero -> MaxNotZero -> MaxNotZero)
-> Ord MaxNotZero
MaxNotZero -> MaxNotZero -> Bool
MaxNotZero -> MaxNotZero -> Ordering
MaxNotZero -> MaxNotZero -> MaxNotZero
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
$ccompare :: MaxNotZero -> MaxNotZero -> Ordering
compare :: MaxNotZero -> MaxNotZero -> Ordering
$c< :: MaxNotZero -> MaxNotZero -> Bool
< :: MaxNotZero -> MaxNotZero -> Bool
$c<= :: MaxNotZero -> MaxNotZero -> Bool
<= :: MaxNotZero -> MaxNotZero -> Bool
$c> :: MaxNotZero -> MaxNotZero -> Bool
> :: MaxNotZero -> MaxNotZero -> Bool
$c>= :: MaxNotZero -> MaxNotZero -> Bool
>= :: MaxNotZero -> MaxNotZero -> Bool
$cmax :: MaxNotZero -> MaxNotZero -> MaxNotZero
max :: MaxNotZero -> MaxNotZero -> MaxNotZero
$cmin :: MaxNotZero -> MaxNotZero -> MaxNotZero
min :: MaxNotZero -> MaxNotZero -> MaxNotZero
Ord, Int -> MaxNotZero -> ShowS
[MaxNotZero] -> ShowS
MaxNotZero -> String
(Int -> MaxNotZero -> ShowS)
-> (MaxNotZero -> String)
-> ([MaxNotZero] -> ShowS)
-> Show MaxNotZero
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> MaxNotZero -> ShowS
showsPrec :: Int -> MaxNotZero -> ShowS
$cshow :: MaxNotZero -> String
show :: MaxNotZero -> String
$cshowList :: [MaxNotZero] -> ShowS
showList :: [MaxNotZero] -> ShowS
Show)

-- |
--
-- >>> MaxNotZero (NotZero True (pos 7)) ^. notZero
-- NotZero True (Positive 7)
instance HasNotZero MaxNotZero where
  notZero :: Lens' MaxNotZero NotZero
notZero =
    (Unwrapped MaxNotZero -> f (Unwrapped MaxNotZero))
-> MaxNotZero -> f MaxNotZero
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
Iso
  MaxNotZero MaxNotZero (Unwrapped MaxNotZero) (Unwrapped MaxNotZero)
_Wrapped ((Unwrapped MaxNotZero -> f (Unwrapped MaxNotZero))
 -> MaxNotZero -> f MaxNotZero)
-> ((NotZero -> f NotZero)
    -> Unwrapped MaxNotZero -> f (Unwrapped MaxNotZero))
-> (NotZero -> f NotZero)
-> MaxNotZero
-> f MaxNotZero
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (NotZero -> f NotZero)
-> Unwrapped MaxNotZero -> f (Unwrapped MaxNotZero)
(NotZero -> f NotZero) -> NotZero -> f NotZero
forall a. HasNotZero a => Lens' a NotZero
Lens' NotZero NotZero
notZero

-- |
--
-- >>> MaxNotZero (NotZero True (pos 7)) ^? _NotZero
-- Just (NotZero True (Positive 7))
instance AsNotZero MaxNotZero where
  _NotZero :: Prism' MaxNotZero NotZero
_NotZero =
    p (Unwrapped MaxNotZero) (f (Unwrapped MaxNotZero))
-> p MaxNotZero (f MaxNotZero)
p NotZero (f NotZero) -> p MaxNotZero (f MaxNotZero)
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
Iso
  MaxNotZero MaxNotZero (Unwrapped MaxNotZero) (Unwrapped MaxNotZero)
_Wrapped (p NotZero (f NotZero) -> p MaxNotZero (f MaxNotZero))
-> (p NotZero (f NotZero) -> p NotZero (f NotZero))
-> p NotZero (f NotZero)
-> p MaxNotZero (f MaxNotZero)
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. p NotZero (f NotZero) -> p NotZero (f NotZero)
forall a. AsNotZero a => Prism' a NotZero
Prism' NotZero NotZero
_NotZero

instance
  (MaxNotZero ~ a) =>
  Rewrapped MaxNotZero a

-- |
--
-- >>> MaxNotZero (NotZero True (pos 7)) ^. _Wrapped'
-- NotZero True (Positive 7)
instance Wrapped MaxNotZero where
  type Unwrapped MaxNotZero = NotZero
  _Wrapped' :: Iso
  MaxNotZero MaxNotZero (Unwrapped MaxNotZero) (Unwrapped MaxNotZero)
_Wrapped' =
    (MaxNotZero -> NotZero)
-> (NotZero -> MaxNotZero)
-> Iso MaxNotZero MaxNotZero NotZero NotZero
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso
      (\(MaxNotZero NotZero
x) -> NotZero
x)
      NotZero -> MaxNotZero
MaxNotZero

-- |
--
-- >>> MaxNotZero (NotZero True (pos 3)) <> MaxNotZero (NotZero True (pos 7))
-- MaxNotZero (NotZero True (Positive 7))
instance Semigroup MaxNotZero where
  MaxNotZero NotZero
x <> :: MaxNotZero -> MaxNotZero -> MaxNotZero
<> MaxNotZero NotZero
y =
    NotZero -> MaxNotZero
MaxNotZero (NotZero -> NotZero -> NotZero
forall a. Ord a => a -> a -> a
max NotZero
x NotZero
y)

-- |
--
-- >>> MinNotZero (NotZero True (pos 3)) <> MinNotZero (NotZero True (pos 7))
-- MinNotZero (NotZero True (Positive 3))
--
-- >>> MinNotZero (NotZero False (pos 3)) <> MinNotZero (NotZero True (pos 1))
-- MinNotZero (NotZero False (Positive 3))
newtype MinNotZero
  = MinNotZero
      NotZero
  deriving (MinNotZero -> MinNotZero -> Bool
(MinNotZero -> MinNotZero -> Bool)
-> (MinNotZero -> MinNotZero -> Bool) -> Eq MinNotZero
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: MinNotZero -> MinNotZero -> Bool
== :: MinNotZero -> MinNotZero -> Bool
$c/= :: MinNotZero -> MinNotZero -> Bool
/= :: MinNotZero -> MinNotZero -> Bool
Eq, Eq MinNotZero
Eq MinNotZero =>
(MinNotZero -> MinNotZero -> Ordering)
-> (MinNotZero -> MinNotZero -> Bool)
-> (MinNotZero -> MinNotZero -> Bool)
-> (MinNotZero -> MinNotZero -> Bool)
-> (MinNotZero -> MinNotZero -> Bool)
-> (MinNotZero -> MinNotZero -> MinNotZero)
-> (MinNotZero -> MinNotZero -> MinNotZero)
-> Ord MinNotZero
MinNotZero -> MinNotZero -> Bool
MinNotZero -> MinNotZero -> Ordering
MinNotZero -> MinNotZero -> MinNotZero
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
$ccompare :: MinNotZero -> MinNotZero -> Ordering
compare :: MinNotZero -> MinNotZero -> Ordering
$c< :: MinNotZero -> MinNotZero -> Bool
< :: MinNotZero -> MinNotZero -> Bool
$c<= :: MinNotZero -> MinNotZero -> Bool
<= :: MinNotZero -> MinNotZero -> Bool
$c> :: MinNotZero -> MinNotZero -> Bool
> :: MinNotZero -> MinNotZero -> Bool
$c>= :: MinNotZero -> MinNotZero -> Bool
>= :: MinNotZero -> MinNotZero -> Bool
$cmax :: MinNotZero -> MinNotZero -> MinNotZero
max :: MinNotZero -> MinNotZero -> MinNotZero
$cmin :: MinNotZero -> MinNotZero -> MinNotZero
min :: MinNotZero -> MinNotZero -> MinNotZero
Ord, Int -> MinNotZero -> ShowS
[MinNotZero] -> ShowS
MinNotZero -> String
(Int -> MinNotZero -> ShowS)
-> (MinNotZero -> String)
-> ([MinNotZero] -> ShowS)
-> Show MinNotZero
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> MinNotZero -> ShowS
showsPrec :: Int -> MinNotZero -> ShowS
$cshow :: MinNotZero -> String
show :: MinNotZero -> String
$cshowList :: [MinNotZero] -> ShowS
showList :: [MinNotZero] -> ShowS
Show)

-- |
--
-- >>> MinNotZero (NotZero False (pos 3)) ^. notZero
-- NotZero False (Positive 3)
instance HasNotZero MinNotZero where
  notZero :: Lens' MinNotZero NotZero
notZero =
    (Unwrapped MinNotZero -> f (Unwrapped MinNotZero))
-> MinNotZero -> f MinNotZero
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
Iso
  MinNotZero MinNotZero (Unwrapped MinNotZero) (Unwrapped MinNotZero)
_Wrapped ((Unwrapped MinNotZero -> f (Unwrapped MinNotZero))
 -> MinNotZero -> f MinNotZero)
-> ((NotZero -> f NotZero)
    -> Unwrapped MinNotZero -> f (Unwrapped MinNotZero))
-> (NotZero -> f NotZero)
-> MinNotZero
-> f MinNotZero
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (NotZero -> f NotZero)
-> Unwrapped MinNotZero -> f (Unwrapped MinNotZero)
(NotZero -> f NotZero) -> NotZero -> f NotZero
forall a. HasNotZero a => Lens' a NotZero
Lens' NotZero NotZero
notZero

-- |
--
-- >>> MinNotZero (NotZero False (pos 3)) ^? _NotZero
-- Just (NotZero False (Positive 3))
instance AsNotZero MinNotZero where
  _NotZero :: Prism' MinNotZero NotZero
_NotZero =
    p (Unwrapped MinNotZero) (f (Unwrapped MinNotZero))
-> p MinNotZero (f MinNotZero)
p NotZero (f NotZero) -> p MinNotZero (f MinNotZero)
forall s t. Rewrapping s t => Iso s t (Unwrapped s) (Unwrapped t)
Iso
  MinNotZero MinNotZero (Unwrapped MinNotZero) (Unwrapped MinNotZero)
_Wrapped (p NotZero (f NotZero) -> p MinNotZero (f MinNotZero))
-> (p NotZero (f NotZero) -> p NotZero (f NotZero))
-> p NotZero (f NotZero)
-> p MinNotZero (f MinNotZero)
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. p NotZero (f NotZero) -> p NotZero (f NotZero)
forall a. AsNotZero a => Prism' a NotZero
Prism' NotZero NotZero
_NotZero

instance
  (MinNotZero ~ a) =>
  Rewrapped MinNotZero a

-- |
--
-- >>> MinNotZero (NotZero False (pos 3)) ^. _Wrapped'
-- NotZero False (Positive 3)
instance Wrapped MinNotZero where
  type Unwrapped MinNotZero = NotZero
  _Wrapped' :: Iso
  MinNotZero MinNotZero (Unwrapped MinNotZero) (Unwrapped MinNotZero)
_Wrapped' =
    (MinNotZero -> NotZero)
-> (NotZero -> MinNotZero)
-> Iso MinNotZero MinNotZero NotZero NotZero
forall s a b t. (s -> a) -> (b -> t) -> Iso s t a b
iso
      (\(MinNotZero NotZero
x) -> NotZero
x)
      NotZero -> MinNotZero
MinNotZero

-- |
--
-- >>> MinNotZero (NotZero True (pos 3)) <> MinNotZero (NotZero True (pos 7))
-- MinNotZero (NotZero True (Positive 3))
instance Semigroup MinNotZero where
  MinNotZero NotZero
x <> :: MinNotZero -> MinNotZero -> MinNotZero
<> MinNotZero NotZero
y =
    NotZero -> MinNotZero
MinNotZero (NotZero -> NotZero -> NotZero
forall a. Ord a => a -> a -> a
min NotZero
x NotZero
y)

-- | Serialises a 'NotZero' to a JSON number.
--
-- >>> fromJSON (Number 5) :: Result NotZero
-- Success (NotZero True (Positive 5))
--
-- >>> fromJSON (Number (-3)) :: Result NotZero
-- Success (NotZero False (Positive 3))
--
-- >>> decode "7" :: Maybe NotZero
-- Just (NotZero True (Positive 7))
--
-- >>> decode "-2" :: Maybe NotZero
-- Just (NotZero False (Positive 2))
--
-- >>> decode "0" :: Maybe NotZero
-- Nothing
instance ToJSON NotZero where
  toJSON :: NotZero -> Value
toJSON =
    NotZero -> Value
forall a. HasNotZero a => a -> Value
toJsonNotZero
  toEncoding :: NotZero -> Encoding
toEncoding NotZero
nz =
    Integer -> Encoding
forall a. ToJSON a => a -> Encoding
toEncoding (NotZero -> Integer
notZeroInteger NotZero
nz)

-- | Parses a 'NotZero' from a JSON number, failing on zero.
--
-- >>> decode "5" :: Maybe NotZero
-- Just (NotZero True (Positive 5))
instance FromJSON NotZero where
  parseJSON :: Value -> Parser NotZero
parseJSON =
    Value -> Parser NotZero
parseJsonNotZero

-- | Serialises any value with a 'HasNotZero' instance to a JSON 'Value'.
--
-- >>> toJsonNotZero (NotZero True (pos 5))
-- Number 5.0
--
-- >>> toJsonNotZero (NotZero False (pos 3))
-- Number (-3.0)
--
-- >>> toJsonNotZero (SumNotZero (NotZero True (pos 7)))
-- Number 7.0
--
-- >>> toJsonNotZero (MaxNotZero (NotZero False (pos 2)))
-- Number (-2.0)
--
-- >>> toJsonNotZero (MinNotZero (NotZero True (pos 1)))
-- Number 1.0
{-# SPECIALIZE toJsonNotZero ::
  NotZero ->
  Value
  #-}
{-# INLINE toJsonNotZero #-}
toJsonNotZero ::
  (HasNotZero a) =>
  a ->
  Value
toJsonNotZero :: forall a. HasNotZero a => a -> Value
toJsonNotZero a
a =
  Integer -> Value
forall a. ToJSON a => a -> Value
toJSON (NotZero -> Integer
notZeroInteger (a
a a -> Getting NotZero a NotZero -> NotZero
forall s a. s -> Getting a s a -> a
^. Getting NotZero a NotZero
forall a. HasNotZero a => Lens' a NotZero
Lens' a NotZero
notZero))

-- | Parses a JSON value into a 'NotZero', failing on zero.
--
-- >>> parse parseJsonNotZero (Number 5)
-- Success (NotZero True (Positive 5))
--
-- >>> parse parseJsonNotZero (Number (-3))
-- Success (NotZero False (Positive 3))
--
-- >>> parse parseJsonNotZero (Number 0)
-- Error "parse failed, NotZero: expected non-zero integer"
{-# INLINE parseJsonNotZero #-}
parseJsonNotZero ::
  Value ->
  Parser NotZero
parseJsonNotZero :: Value -> Parser NotZero
parseJsonNotZero Value
v =
  Value -> Parser Integer
forall a. FromJSON a => Value -> Parser a
parseJSON Value
v Parser Integer -> (Integer -> Parser NotZero) -> Parser NotZero
forall a b. Parser a -> (a -> Parser b) -> Parser b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Integer
n ->
    if Integer
n Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
0
      then String -> Parser NotZero
forall a. String -> Parser a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"parse failed, NotZero: expected non-zero integer"
      else
        NotZero -> Parser NotZero
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
          ( if Integer
n Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
0
              then Bool -> Positive -> NotZero
NotZero Bool
False (Integer -> Positive
Positive (Integer -> Integer
forall a. Num a => a -> a
negate Integer
n))
              else Bool -> Positive -> NotZero
NotZero Bool
True (Integer -> Positive
Positive Integer
n)
          )

-- | Serialises a 'SumNotZero' to a JSON number.
--
-- >>> encode (SumNotZero (NotZero True (pos 7)))
-- "7"
instance ToJSON SumNotZero where
  toJSON :: SumNotZero -> Value
toJSON =
    SumNotZero -> Value
forall a. HasNotZero a => a -> Value
toJsonNotZero
  toEncoding :: SumNotZero -> Encoding
toEncoding (SumNotZero NotZero
nz) =
    Integer -> Encoding
forall a. ToJSON a => a -> Encoding
toEncoding (NotZero -> Integer
notZeroInteger NotZero
nz)

-- | Parses a 'SumNotZero' from a JSON number, failing on zero.
--
-- >>> decode "7" :: Maybe SumNotZero
-- Just (SumNotZero (NotZero True (Positive 7)))
--
-- >>> decode "0" :: Maybe SumNotZero
-- Nothing
instance FromJSON SumNotZero where
  parseJSON :: Value -> Parser SumNotZero
parseJSON Value
v =
    Value -> Parser NotZero
parseJsonNotZero Value
v Parser NotZero
-> (NotZero -> Parser SumNotZero) -> Parser SumNotZero
forall a b. Parser a -> (a -> Parser b) -> Parser b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \NotZero
n -> SumNotZero -> Parser SumNotZero
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (NotZero -> SumNotZero
SumNotZero NotZero
n)

-- | Serialises a 'MaxNotZero' to a JSON number.
--
-- >>> encode (MaxNotZero (NotZero False (pos 2)))
-- "-2"
instance ToJSON MaxNotZero where
  toJSON :: MaxNotZero -> Value
toJSON =
    MaxNotZero -> Value
forall a. HasNotZero a => a -> Value
toJsonNotZero
  toEncoding :: MaxNotZero -> Encoding
toEncoding (MaxNotZero NotZero
nz) =
    Integer -> Encoding
forall a. ToJSON a => a -> Encoding
toEncoding (NotZero -> Integer
notZeroInteger NotZero
nz)

-- | Parses a 'MaxNotZero' from a JSON number, failing on zero.
--
-- >>> decode "-2" :: Maybe MaxNotZero
-- Just (MaxNotZero (NotZero False (Positive 2)))
--
-- >>> decode "0" :: Maybe MaxNotZero
-- Nothing
instance FromJSON MaxNotZero where
  parseJSON :: Value -> Parser MaxNotZero
parseJSON Value
v =
    Value -> Parser NotZero
parseJsonNotZero Value
v Parser NotZero
-> (NotZero -> Parser MaxNotZero) -> Parser MaxNotZero
forall a b. Parser a -> (a -> Parser b) -> Parser b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \NotZero
n -> MaxNotZero -> Parser MaxNotZero
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (NotZero -> MaxNotZero
MaxNotZero NotZero
n)

-- | Serialises a 'MinNotZero' to a JSON number.
--
-- >>> encode (MinNotZero (NotZero True (pos 1)))
-- "1"
instance ToJSON MinNotZero where
  toJSON :: MinNotZero -> Value
toJSON =
    MinNotZero -> Value
forall a. HasNotZero a => a -> Value
toJsonNotZero
  toEncoding :: MinNotZero -> Encoding
toEncoding (MinNotZero NotZero
nz) =
    Integer -> Encoding
forall a. ToJSON a => a -> Encoding
toEncoding (NotZero -> Integer
notZeroInteger NotZero
nz)

-- | Parses a 'MinNotZero' from a JSON number, failing on zero.
--
-- >>> decode "1" :: Maybe MinNotZero
-- Just (MinNotZero (NotZero True (Positive 1)))
--
-- >>> decode "0" :: Maybe MinNotZero
-- Nothing
instance FromJSON MinNotZero where
  parseJSON :: Value -> Parser MinNotZero
parseJSON Value
v =
    Value -> Parser NotZero
parseJsonNotZero Value
v Parser NotZero
-> (NotZero -> Parser MinNotZero) -> Parser MinNotZero
forall a b. Parser a -> (a -> Parser b) -> Parser b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \NotZero
n -> MinNotZero -> Parser MinNotZero
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (NotZero -> MinNotZero
MinNotZero NotZero
n)

-- | Embed a 'Positive' as a positive 'NotZero'.
--
-- >>> positiveNotZero (pos 5)
-- NotZero True (Positive 5)
positiveNotZero ::
  Positive ->
  NotZero
positiveNotZero :: Positive -> NotZero
positiveNotZero =
  Bool -> Positive -> NotZero
NotZero Bool
True

-- | Embed a 'Positive' as a negative 'NotZero'.
--
-- >>> negativeNotZero (pos 5)
-- NotZero False (Positive 5)
negativeNotZero ::
  Positive ->
  NotZero
negativeNotZero :: Positive -> NotZero
negativeNotZero =
  Bool -> Positive -> NotZero
NotZero Bool
False

-- | Extract the magnitude from a 'NotZero'.
--
-- >>> notZeroPositive (NotZero True (pos 5))
-- Positive 5
--
-- >>> notZeroPositive (NotZero False (pos 3))
-- Positive 3
notZeroPositive ::
  NotZero ->
  Positive
notZeroPositive :: NotZero -> Positive
notZeroPositive (NotZero Bool
_ Positive
p) =
  Positive
p

-- | Convert a 'NotZero' to an 'Integer'.
--
-- >>> notZeroInteger (NotZero True (pos 5))
-- 5
--
-- >>> notZeroInteger (NotZero False (pos 3))
-- -3
notZeroInteger ::
  NotZero ->
  Integer
notZeroInteger :: NotZero -> Integer
notZeroInteger (NotZero Bool
s (Positive Integer
n)) =
  if Bool
s then Integer
n else Integer -> Integer
forall a. Num a => a -> a
negate Integer
n

-- | Test if a 'NotZero' is positive.
--
-- >>> isPositive (NotZero True (pos 5))
-- True
--
-- >>> isPositive (NotZero False (pos 5))
-- False
isPositive ::
  NotZero ->
  Bool
isPositive :: NotZero -> Bool
isPositive (NotZero Bool
s Positive
_) =
  Bool
s

-- | Test if a 'NotZero' is negative.
--
-- >>> isNegative (NotZero False (pos 5))
-- True
--
-- >>> isNegative (NotZero True (pos 5))
-- False
isNegative ::
  NotZero ->
  Bool
isNegative :: NotZero -> Bool
isNegative (NotZero Bool
s Positive
_) =
  Bool -> Bool
not Bool
s

-- | Negate a 'NotZero'.
--
-- >>> negateNZ (NotZero True (pos 5))
-- NotZero False (Positive 5)
--
-- >>> negateNZ (NotZero False (pos 3))
-- NotZero True (Positive 3)
negateNZ ::
  NotZero ->
  NotZero
negateNZ :: NotZero -> NotZero
negateNZ (NotZero Bool
s Positive
p) =
  Bool -> Positive -> NotZero
NotZero (Bool -> Bool
not Bool
s) Positive
p

-- | Absolute value as a 'Positive'.
--
-- >>> absoluteNZ (NotZero True (pos 5))
-- Positive 5
--
-- >>> absoluteNZ (NotZero False (pos 3))
-- Positive 3
absoluteNZ ::
  NotZero ->
  Positive
absoluteNZ :: NotZero -> Positive
absoluteNZ =
  NotZero -> Positive
notZeroPositive

-- | Signum: positive one or negative one.
--
-- >>> signumNZ (NotZero True (pos 99))
-- NotZero True (Positive 1)
--
-- >>> signumNZ (NotZero False (pos 42))
-- NotZero False (Positive 1)
signumNZ ::
  NotZero ->
  NotZero
signumNZ :: NotZero -> NotZero
signumNZ (NotZero Bool
s Positive
_) =
  Bool -> Positive -> NotZero
NotZero Bool
s Positive
one'

-- | Add two 'NotZero' values. Returns 'Nothing' if the result is zero.
--
-- >>> plusNZ (NotZero True (pos 3)) (NotZero True (pos 4))
-- Just (NotZero True (Positive 7))
--
-- >>> plusNZ (NotZero True (pos 3)) (NotZero False (pos 3))
-- Nothing
--
-- >>> plusNZ (NotZero True (pos 5)) (NotZero False (pos 3))
-- Just (NotZero True (Positive 2))
--
-- >>> plusNZ (NotZero False (pos 5)) (NotZero True (pos 3))
-- Just (NotZero False (Positive 2))
plusNZ ::
  NotZero ->
  NotZero ->
  Maybe NotZero
plusNZ :: NotZero -> NotZero -> Maybe NotZero
plusNZ (NotZero Bool
s1 (Positive Integer
x)) (NotZero Bool
s2 (Positive Integer
y)) =
  case (Bool
s1, Bool
s2) of
    (Bool
True, Bool
True) -> NotZero -> Maybe NotZero
forall a. a -> Maybe a
Just (Bool -> Positive -> NotZero
NotZero Bool
True (Integer -> Positive
Positive (Integer
x Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
y)))
    (Bool
False, Bool
False) -> NotZero -> Maybe NotZero
forall a. a -> Maybe a
Just (Bool -> Positive -> NotZero
NotZero Bool
False (Integer -> Positive
Positive (Integer
x Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
y)))
    (Bool
True, Bool
False)
      | Integer
x Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
y -> Maybe NotZero
forall a. Maybe a
Nothing
      | Integer
x Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
y -> NotZero -> Maybe NotZero
forall a. a -> Maybe a
Just (Bool -> Positive -> NotZero
NotZero Bool
False (Integer -> Positive
Positive (Integer
y Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
x)))
      | Bool
True -> NotZero -> Maybe NotZero
forall a. a -> Maybe a
Just (Bool -> Positive -> NotZero
NotZero Bool
True (Integer -> Positive
Positive (Integer
x Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
y)))
    (Bool
False, Bool
True)
      | Integer
x Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
== Integer
y -> Maybe NotZero
forall a. Maybe a
Nothing
      | Integer
y Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
< Integer
x -> NotZero -> Maybe NotZero
forall a. a -> Maybe a
Just (Bool -> Positive -> NotZero
NotZero Bool
False (Integer -> Positive
Positive (Integer
x Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
y)))
      | Bool
True -> NotZero -> Maybe NotZero
forall a. a -> Maybe a
Just (Bool -> Positive -> NotZero
NotZero Bool
True (Integer -> Positive
Positive (Integer
y Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
x)))

-- | Multiply two 'NotZero' values. Always non-zero.
--
-- >>> multiplyNZ (NotZero True (pos 3)) (NotZero True (pos 4))
-- NotZero True (Positive 12)
--
-- >>> multiplyNZ (NotZero False (pos 3)) (NotZero True (pos 4))
-- NotZero False (Positive 12)
--
-- >>> multiplyNZ (NotZero False (pos 3)) (NotZero False (pos 4))
-- NotZero True (Positive 12)
multiplyNZ ::
  NotZero ->
  NotZero ->
  NotZero
multiplyNZ :: NotZero -> NotZero -> NotZero
multiplyNZ (NotZero Bool
s1 (Positive Integer
x)) (NotZero Bool
s2 (Positive Integer
y)) =
  Bool -> Positive -> NotZero
NotZero (Bool
s1 Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
== Bool
s2) (Integer -> Positive
Positive (Integer
x Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
y))

-- | Return the 'NotZero' if the prism matches, otherwise positive one.
--
-- >>> notZeroOr (5 :: Integer)
-- NotZero True (Positive 5)
--
-- >>> notZeroOr (0 :: Integer)
-- NotZero True (Positive 1)
--
-- >>> notZeroOr (-3 :: Integer)
-- NotZero False (Positive 3)
notZeroOr ::
  (AsNotZero a) =>
  a ->
  NotZero
notZeroOr :: forall a. AsNotZero a => a -> NotZero
notZeroOr a
n =
  NotZero -> Maybe NotZero -> NotZero
forall a. a -> Maybe a -> a
fromMaybe (Bool -> Positive -> NotZero
NotZero Bool
True Positive
one') (a
n a -> Getting (First NotZero) a NotZero -> Maybe NotZero
forall s a. s -> Getting (First a) s a -> Maybe a
^? Getting (First NotZero) a NotZero
forall a. AsNotZero a => Prism' a NotZero
Prism' a NotZero
_NotZero)

-- | Prism from 'NotZero' to 'Positive' (matches only positive values).
--
-- >>> (NotZero True (pos 5)) ^? _Positive
-- Just (Positive 5)
--
-- >>> (NotZero False (pos 5)) ^? _Positive
-- Nothing
instance AsPositive NotZero where
  _Positive :: Prism' NotZero Positive
_Positive =
    (Positive -> NotZero)
-> (NotZero -> Maybe Positive) -> Prism' NotZero Positive
forall b s a. (b -> s) -> (s -> Maybe a) -> Prism s s a b
prism'
      Positive -> NotZero
positiveNotZero
      (\(NotZero Bool
s Positive
p) -> if Bool
s then Positive -> Maybe Positive
forall a. a -> Maybe a
Just Positive
p else Maybe Positive
forall a. Maybe a
Nothing)