diff --git a/src/Data/IntegerInterval.hs b/src/Data/IntegerInterval.hs index 37bbdbe..9ab87de 100644 --- a/src/Data/IntegerInterval.hs +++ b/src/Data/IntegerInterval.hs @@ -50,6 +50,7 @@ module Data.IntegerInterval , lowerBound' , upperBound' , width + , memberCount -- * Universal comparison operators , (=!), (>!), (/=!) @@ -309,6 +310,17 @@ width x (Finite lb, Finite ub) -> ub - lb _ -> error "Data.IntegerInterval.width: unbounded interval" +-- | How many integers lie within the (bounded) interval. +-- Equal to @Just (width + 1)@ for non-empty, bounded intervals. +-- The @memberCount@ of an unbounded interval is @Nothing@. +memberCount :: IntegerInterval -> Maybe Integer +memberCount x + | null x = Just 0 + | otherwise = + case (lowerBound x, upperBound x) of + (Finite lb, Finite ub) -> Just (ub - lb + 1) + _ -> Nothing + -- | pick up an element from the interval if the interval is not empty. pickup :: IntegerInterval -> Maybe Integer pickup x = diff --git a/test/TestIntegerInterval.hs b/test/TestIntegerInterval.hs index 9f00fdc..681734a 100644 --- a/test/TestIntegerInterval.hs +++ b/test/TestIntegerInterval.hs @@ -275,6 +275,20 @@ prop_width_singleton = forAll arbitrary $ \x -> IntegerInterval.width (IntegerInterval.singleton x) == 0 +{-------------------------------------------------------------------- + memberCount +--------------------------------------------------------------------} + +case_memberCount_null = + IntegerInterval.memberCount IntegerInterval.empty @?= Just 0 + +case_memberCount_positive = + IntegerInterval.memberCount (0 <=..< 10) @?= Just 10 + +prop_memberCount_singleton = + forAll arbitrary $ \x -> + IntegerInterval.memberCount (IntegerInterval.singleton x) == Just 1 + {-------------------------------------------------------------------- map --------------------------------------------------------------------}