module Util.Positive
( Positive (..)
, mkPositive
, lengthNE
, replicateNE
) where
import Data.Aeson (FromJSON, ToJSON)
import Data.Data (Data)
import Fmt (Buildable, pretty)
import Util.Instances ()
newtype Positive = PositiveUnsafe { unPositive :: Natural }
deriving stock (Eq, Ord, Data)
deriving newtype (Show, Buildable, ToJSON, FromJSON)
mkPositive :: (Integral i, Buildable i) => i -> Either Text Positive
mkPositive a
| a > 0 = Right $ PositiveUnsafe (fromIntegral a)
| otherwise = Left $ "Number is not positive: " <> pretty a
lengthNE :: NonEmpty a -> Positive
lengthNE = PositiveUnsafe . fromIntegral . length
replicateNE :: Positive -> a -> NonEmpty a
replicateNE (PositiveUnsafe i) a = a :| replicate (fromIntegral i - 1) a