packages feed

mixed-types-num 0.5.12 → 0.6.2

raw patch · 14 files changed

Files

changelog.md view
@@ -1,5 +1,9 @@ # mixed-types-num change log +* v 0.6.2 2024-10-05+  * Ring now requires HasIntegersWithSample instead of HasIntegers+  * Field now requires HasRationalsWithSample instead of HasRationals+  * all test suites require HasIntegersWithSample instead of HasIntegers * v 0.5.12 2023-08-14   * compatible with ghc 9.6.2   * remove dependency on mtl
mixed-types-num.cabal view
@@ -1,11 +1,11 @@ cabal-version: 1.12 --- This file has been generated from package.yaml by hpack version 0.35.2.+-- This file has been generated from package.yaml by hpack version 0.36.0. -- -- see: https://github.com/sol/hpack  name:           mixed-types-num-version:        0.5.12+version:        0.6.2 synopsis:       Alternative Prelude with numeric and logic expressions typed bottom-up description:    Please see the README on GitHub at <https://github.com/michalkonecny/mixed-types-num#readme> category:       Math@@ -13,7 +13,7 @@ bug-reports:    https://github.com/michalkonecny/mixed-types-num/issues author:         Michal Konecny maintainer:     mikkonecny@gmail.com-copyright:      2015-2023 Michal Konecny+copyright:      2015-2024 Michal Konecny license:        BSD3 license-file:   LICENSE build-type:     Simple
src/Numeric/MixedTypes/AddSub.hs view
@@ -17,7 +17,7 @@ (     -- * Addition     CanAdd, CanAddAsymmetric(..), CanAddThis, CanAddSameType-    , (+), sum+    , (+), sum, sumWithSample   -- ** Tests     , specCanAdd, specCanAddNotMixed, specCanAddSameType     -- * Subtraction@@ -81,6 +81,9 @@ sum :: (CanAddSameType t, ConvertibleExactly Integer t) => [t] -> t sum xs = List.foldl' add (convertExactly 0) xs +sumWithSample :: (CanAddSameType t, ConvertibleExactlyWithSample Integer t) => t -> [t] -> t+sumWithSample sampleT xs = List.foldl' add (convertExactlyWithSample sampleT 0) xs+ {-|   HSpec properties that each implementation of CanAdd should satisfy.  -}@@ -89,7 +92,8 @@ specCanAdd (T typeName1 :: T t1) (T typeName2 :: T t2) (T typeName3 :: T t3) =   describe (printf "CanAdd %s %s, CanAdd %s %s" typeName1 typeName2 typeName2 typeName3) $ do     it "absorbs 0" $ do-      property $ \ (x :: t1) -> let z = (convertExactly 0 :: t1) in (x + z) ?==?$ x+      property $ \ (x :: t1) (sampleT2 :: t2) -> +        let z = (convertExactlyWithSample sampleT2 0 :: t2) in (x + z) ?==?$ x     it "is commutative" $ do       property $ \ (x :: t1) (y :: t2) -> (x + y) ?==?$ (y + x)     it "is associative" $ do@@ -121,17 +125,20 @@   HSpec properties that each implementation of CanAddSameType should satisfy.  -} specCanAddSameType ::-  (ConvertibleExactly Integer t, Show t,-   HasEqCertainly t t, CanAddSameType t)+  (ConvertibleExactlyWithSample Integer t, Show t,+   HasEqCertainly t t, CanAddSameType t, Arbitrary t)    =>    T t -> Spec specCanAddSameType (T typeName :: T t) =   describe (printf "CanAddSameType %s" typeName) $ do     it "has sum working over integers" $ do-      property $ \ (xsi :: [Integer]) ->-        (sum $ (map convertExactly xsi :: [t])) ?==?$ (convertExactly (sum xsi) :: t)+      property $ \ (xsi :: [Integer]) (sampleT :: t) ->+        (sumWithSample sampleT $ (map (convertExactlyWithSample sampleT) xsi :: [t])) +        ?==?$ +        (convertExactlyWithSample sampleT (sum xsi) :: t)     it "has sum [] = 0" $ do-        (sum ([] :: [t])) ?==?$ (convertExactly 0 :: t)+      property $ \ (sampleT :: t) ->+        (sumWithSample sampleT ([] :: [t])) ?==?$ (convertExactlyWithSample sampleT 0 :: t)   where   (?==?$) :: (HasEqCertainlyAsymmetric a b, Show a, Show b) => a -> b -> Property   (?==?$) = printArgsIfFails2 "?==?" (?==?)@@ -240,9 +247,11 @@ specCanSub (T typeName1 :: T t1) (T typeName2 :: T t2) =   describe (printf "CanSub %s %s" typeName1 typeName2) $ do     it "x-0 = x" $ do-      property $ \ (x :: t1) -> let z = (convertExactly 0 :: t1) in (x - z) ?==?$ x+      property $ \ (x :: t1) (sampleT2 :: t2) -> +        let z = (convertExactlyWithSample sampleT2 0 :: t2) in (x - z) ?==?$ x     it "x-x = 0" $ do-      property $ \ (x :: t1) -> let z = (convertExactly 0 :: t1) in (x - x) ?==?$ z+      property $ \ (x :: t1) (sampleR :: SubType t1 t1) -> +        let z = (convertExactlyWithSample sampleR 0 :: SubType t1 t1) in (x - x) ?==?$ z     it "x-y = x+(-y)" $ do       property $ \ (x :: t1) (y :: t2) ->         (x - y) ?==?$ (x + (negate y))
src/Numeric/MixedTypes/Complex.hs view
@@ -148,27 +148,27 @@      instance (HasEqAsymmetric $t b) => HasEqAsymmetric $t (Complex b) where       type EqCompareType $t (Complex b) = EqCompareType $t b-      equalTo n (a2 :+ i2) = (n == a2) && (convertExactlyTargetSample n 0 == i2)+      equalTo n (a2 :+ i2) = (n == a2) && (convertExactlyWithSample n 0 == i2)      instance (HasEqAsymmetric a $t) => HasEqAsymmetric (Complex a) $t where       type EqCompareType (Complex a) $t = EqCompareType a $t-      equalTo (a1 :+ i1) n = (a1 == n) && (i1 == convertExactlyTargetSample n 0)+      equalTo (a1 :+ i1) n = (a1 == n) && (i1 == convertExactlyWithSample n 0)      instance (CanAddAsymmetric $t b) => CanAddAsymmetric $t (Complex b) where       type AddType $t (Complex b) = Complex (AddType $t b)-      add n (a2 :+ i2) = (n + a2) :+ (convertExactlyTargetSample n 0 + i2)+      add n (a2 :+ i2) = (n + a2) :+ (convertExactlyWithSample n 0 + i2)      instance (CanAddAsymmetric a $t) => CanAddAsymmetric (Complex a) $t where       type AddType (Complex a) $t = Complex (AddType a $t)-      add (a1 :+ i1) n = (a1 + n) :+ (i1 + (convertExactlyTargetSample n 0))+      add (a1 :+ i1) n = (a1 + n) :+ (i1 + (convertExactlyWithSample n 0))      instance (CanSub $t b) => CanSub $t (Complex b) where       type SubType $t (Complex b) = Complex (SubType $t b)-      sub n (a2 :+ i2) = (n - a2) :+ (convertExactlyTargetSample n 0 - i2)+      sub n (a2 :+ i2) = (n - a2) :+ (convertExactlyWithSample n 0 - i2)      instance (CanSub a $t) => CanSub (Complex a) $t where       type SubType (Complex a) $t = Complex (SubType a $t)-      sub (a1 :+ i1) n = (a1 - n) :+ (i1 - (convertExactlyTargetSample n 0))+      sub (a1 :+ i1) n = (a1 - n) :+ (i1 - (convertExactlyWithSample n 0))      instance       (CanMulAsymmetric $t b) => CanMulAsymmetric $t (Complex b)
src/Numeric/MixedTypes/Div.hs view
@@ -102,15 +102,16 @@         (isCertainlyNonZero x && isCertainlyNonZero (recip x)) ==>           recip (recip x) ?==?$ x     it "x/1 = x" $ do-      property $ \ (x :: t1) -> let one = (convertExactly 1 :: t2) in (x / one) ?==?$ x+      property $ \ (x :: t1) (sampleT2 :: t2) -> +        let one = (convertExactlyWithSample sampleT2 1 :: t2) in (x / one) ?==?$ x     it "x/x = 1" $ do-      property $ \ (x :: t1) ->+      property $ \ (x :: t1) (sampleR :: DivType t1 t1) ->         (isCertainlyNonZero x) ==>-          let one = (convertExactly 1 :: t1) in (x / x) ?==?$ one+          let one = (convertExactlyWithSample sampleR 1 :: DivType t1 t1) in (x / x) ?==?$ one     it "x/y = x*(1/y)" $ do-      property $ \ (x :: t1) (y :: t2) ->+      property $ \ (x :: t1) (y :: t2) (sampleT1 :: t1) ->         (isCertainlyNonZero y) ==>-          let one = (convertExactly 1 :: t1) in (x / y) ?==?$ x * (one/y)+          let one = (convertExactlyWithSample sampleT1 1 :: t1) in (x / y) ?==?$ x * (one/y)   where   infix 4 ?==?$   (?==?$) :: (HasEqCertainlyAsymmetric a b, Show a, Show b) => a -> b -> Property
src/Numeric/MixedTypes/Eq.hs view
@@ -385,19 +385,20 @@   HSpec properties that each implementation of CanTestZero should satisfy.  -} specCanTestZero ::-  (CanTestZero t, ConvertibleExactly Integer t)+  (CanTestZero t, ConvertibleExactlyWithSample Integer t, Arbitrary t, P.Show t)   =>   T t -> Spec specCanTestZero (T typeName :: T t) =   describe (printf "CanTestZero %s" typeName) $ do     it "converted non-zero Integer is not isCertainlyZero" $ do-      property $ \ (x :: Integer) ->-        x /= 0 ==> (not $ isCertainlyZero (convertExactly x :: t))+      property $ \ (x :: Integer) (sampleT :: t) ->+        x /= 0 ==> (not $ isCertainlyZero (convertExactlyWithSample sampleT x :: t))     it "converted non-zero Integer is isCertainlyNonZero" $ do-      property $ \ (x :: Integer) ->-        x /= 0 ==> (isCertainlyNonZero (convertExactly x :: t))+      property $ \ (x :: Integer) (sampleT :: t) ->+        x /= 0 ==> (isCertainlyNonZero (convertExactlyWithSample sampleT x :: t))     it "converted 0.0 is not isCertainlyNonZero" $ do-      (isCertainlyNonZero (convertExactly 0 :: t)) `shouldBe` False+      property $ \ (sampleT :: t) ->+        (isCertainlyNonZero (convertExactlyWithSample sampleT 0 :: t)) `shouldBe` False  instance CanTestZero Int instance CanTestZero Integer@@ -434,7 +435,7 @@   HSpec properties that each implementation of CanPickNonZero should satisfy.  -} specCanPickNonZero ::-  (CanPickNonZero t, CanTestZero t, ConvertibleExactly Integer t, Show t, Arbitrary t)+  (CanPickNonZero t, CanTestZero t, ConvertibleExactlyWithSample Integer t, Show t, Arbitrary t)   =>   T t -> Spec specCanPickNonZero (T typeName :: T t) =@@ -447,9 +448,11 @@           Just (v, _) -> isCertainlyNonZero v           _ -> False)     it "returns Nothing when all the elements are 0" $ do-      case pickNonZero [(convertExactly i :: t, ()) | i <- [0,0,0]] of-        Nothing -> True-        _ -> False+      property $ \ (sampleT :: t) ->+        let z = convertExactlyWithSample sampleT 0 :: t in+        case pickNonZero [(z, ()), (z, ()), (z, ())] of+          Nothing -> True+          _ -> False  instance CanPickNonZero Int instance CanPickNonZero Integer
src/Numeric/MixedTypes/Field.hs view
@@ -43,7 +43,7 @@  class   (Ring t,-   HasRationals t,+   HasRationalsWithSample t,    CanPowBy t Integer, CanPowBy t Int,    CanDivSameType t, CanRecipSameType t,    CanAddSubMulDivBy t Rational,
src/Numeric/MixedTypes/Literals.hs view
@@ -40,11 +40,12 @@   -- * Generalised if-then-else   , HasIfThenElse(..), HasIfThenElseSameType   -- * Convenient conversions-  , CanBeInteger, integer, integers, HasIntegers, fromInteger_+  , WithSample(..)+  , CanBeInteger, integer, integers, HasIntegers, fromInteger_, HasIntegersWithSample, fromIntegerWithSample   , CanBeInt, int, ints-  , CanBeRational, rational, rationals, HasRationals, fromRational_+  , CanBeRational, rational, rationals, HasRationals, fromRational_, HasRationalsWithSample, fromRationalWithSample   , CanBeDouble, double, doubles-  , ConvertibleExactly(..), convertExactly, convertExactlyTargetSample+  , ConvertibleExactly(..), convertExactly, convertExactlyWithSample   , ConvertResult, ConvertError, convError   -- * Prelude List operations versions without Int   , (!!), length, replicate, take, drop, splitAt@@ -55,7 +56,7 @@   , printArgsIfFails2   -- * Helper functions   , convertFirst, convertSecond-  , convertFirstUsing, convertSecondUsing+  , convertFirstUsing, convertSecondUsing, ConvertibleExactlyWithSample ) where @@ -133,6 +134,12 @@ fromInteger_ :: (HasIntegers t) => Integer -> t fromInteger_ = convertExactly +data WithSample s t = WithSample s t++type HasIntegersWithSample t = ConvertibleExactlyWithSample Integer t+fromIntegerWithSample :: (HasIntegersWithSample t) => t -> Integer -> t+fromIntegerWithSample sampleT n = convertExactlyWithSample sampleT n+ (!!) :: (CanBeInteger n) => [a] -> n -> a list !! ix = List.genericIndex list (integer ix) -- list !! ix = List.genericIndex list (P.max 0 ((integer ix) P.- 1)) -- deliberately wrong - test the test!@@ -190,6 +197,10 @@ fromRational_ :: (HasRationals t) => Rational -> t fromRational_ = convertExactly +type HasRationalsWithSample t = ConvertibleExactlyWithSample Rational t+fromRationalWithSample :: (HasRationalsWithSample t) => t -> Rational -> t+fromRationalWithSample sampleT q = convertExactlyWithSample sampleT q+ type CanBeDouble t = Convertible t Double double :: (CanBeDouble t) => t -> Double double = convert@@ -206,27 +217,58 @@   default safeConvertExactly :: (Convertible t1 t2) => t1 -> ConvertResult t2   safeConvertExactly = safeConvert +type ConvertibleExactlyWithSample t1 t2 = ConvertibleExactly (WithSample t2 t1) t2+ convertExactly :: (ConvertibleExactly t1 t2) => t1 -> t2 convertExactly a =   case safeConvertExactly a of     Right v -> v     Left err -> error (show err) -convertExactlyTargetSample :: (ConvertibleExactly t1 t2) => t2 -> t1 -> t2-convertExactlyTargetSample _sample = convertExactly+convertExactlyWithSample :: ConvertibleExactlyWithSample t1 t2 => t2 -> t1 -> t2+convertExactlyWithSample sampleT a = convertExactly (WithSample sampleT a) ++-- HasIntegers Integer, CanBeInteger Integer instance ConvertibleExactly Integer Integer -- use CVT instance by default+-- CanBeInteger Int instance ConvertibleExactly Int Integer +-- HasIntegersWithSample Integer+instance ConvertibleExactly (WithSample Integer Integer) Integer where+  safeConvertExactly (WithSample _ value) = safeConvert value++-- HasIntsWithSample Integer+instance ConvertibleExactly (WithSample Int Integer) Int where+  safeConvertExactly (WithSample _ value) = safeConvert value++-- CanBeIntegerWithSample Int+instance ConvertibleExactly (WithSample Integer Int) Integer where+  safeConvertExactly (WithSample _ value) = safeConvert value++-- CanBeInt Int instance ConvertibleExactly Int Int where   safeConvertExactly n = Right n++-- CanBeRational Rational instance ConvertibleExactly Rational Rational where   safeConvertExactly q = Right q +-- HasIntegers Int instance ConvertibleExactly Integer Int instance ConvertibleExactly Int Rational+-- HasIntegers Rational instance ConvertibleExactly Integer Rational +-- HasIntegersWithSample Rational+instance ConvertibleExactly (WithSample Rational Integer) Rational where+  safeConvertExactly (WithSample _sample value) = safeConvert value++-- HasRationalsWithSample Rational+instance ConvertibleExactly (WithSample Rational Rational) Rational where+  safeConvertExactly (WithSample _ value) = safeConvertExactly value++-- HasIntegers Double instance ConvertibleExactly Integer Double where   safeConvertExactly n =     do@@ -235,6 +277,10 @@       (m, fr) | m P.== n P.&& fr P.== (double 0) -> return d       _ -> convError "Integer could not be exactly converted to Double" n +-- HasIntegersWithSample Double+instance ConvertibleExactly (WithSample Double Integer) Double where+  safeConvertExactly (WithSample _ value) = safeConvertExactly value+ instance ConvertibleExactly Int Double where   safeConvertExactly n =     do@@ -243,6 +289,10 @@       (m, fr) | m P.== n P.&& fr P.== (double 0) -> return d       _ -> convError "Int could not be exactly converted to Double" n +-- HasIntsWithSample Double+instance ConvertibleExactly (WithSample Double Int) Double where+  safeConvertExactly (WithSample _ value) = safeConvertExactly value+ instance ConvertibleExactly Double Double where   safeConvertExactly d = Right d @@ -312,13 +362,16 @@   (a -> b -> c) {-^ mixed-type operation -} convertSecond = convertSecondUsing (\ _ b -> convertExactly b) --- instance---   (ConvertibleExactly t1 t2, CanBeErrors es)---   =>---   ConvertibleExactly t1 (CollectErrors es t2)---   where---   safeConvertExactly = fmap pure . safeConvertExactly---+instance (HasIntegers t, Monoid es) => +  -- HasIntegersWithSample (CollectErrors es t)+  ConvertibleExactly (WithSample (CollectErrors es t) Integer) (CollectErrors es t) where+  safeConvertExactly (WithSample _ value) = fmap pure $ safeConvertExactly value++instance (HasRationals t, Monoid es) =>   +  -- HasRationalsWithSample (CollectErrors es t)+  ConvertibleExactly (WithSample (CollectErrors es t) Rational) (CollectErrors es t) where+  safeConvertExactly (WithSample _sample value) = fmap pure $ safeConvertExactly value+  $(declForTypes   [[t| Bool |], [t| Integer |], [t| Int |], [t| Rational |], [t| Double |]]
src/Numeric/MixedTypes/MinMaxAbs.hs view
@@ -255,7 +255,8 @@         (x ?==? x) ==> -- avoid NaN           (negate (negate x)) ?==?$ x     it "takes 0 to 0" $ do-      let z = convertExactly 0 :: t in negate z ?==? z+      property $ \ (sampleT :: t) ->+        let z = convertExactlyWithSample sampleT 0 :: t in negate z ?==? z     it "takes positive to negative" $ do       property $ \ (x :: t) ->         (isFinite x) ==> -- avoid NaN
src/Numeric/MixedTypes/Mul.hs view
@@ -17,7 +17,7 @@ (   -- ** Multiplication   CanMul, CanMulAsymmetric(..), CanMulBy, CanMulSameType-  , (*), product+  , (*), product, productWithSample   -- ** Tests   , specCanMul, specCanMulNotMixed, specCanMulSameType )@@ -74,6 +74,9 @@ product :: (CanMulSameType t, ConvertibleExactly Integer t) => [t] -> t product xs = List.foldl' mul (convertExactly 1) xs +productWithSample :: (CanMulSameType t, ConvertibleExactlyWithSample Integer t) => t -> [t] -> t+productWithSample sampleT xs = List.foldl' mul (convertExactlyWithSample sampleT 1) xs+ {-|   HSpec properties that each implementation of CanMul should satisfy.  -}@@ -82,7 +85,8 @@ specCanMul (T typeName1 :: T t1) (T typeName2 :: T t2) (T typeName3 :: T t3) =   describe (printf "CanMul %s %s, CanMul %s %s" typeName1 typeName2 typeName2 typeName3) $ do     it "absorbs 1" $ do-      property $ \ (x :: t1) -> let one = (convertExactly 1 :: t2) in (x * one) ?==?$ x+      property $ \ (x :: t1) (sampleT2 :: t2) -> +        let one = (convertExactlyWithSample sampleT2 1 :: t2) in (x * one) ?==?$ x     it "is commutative" $ do       property $ \ (x :: t1) (y :: t2) -> (x * y) ?==?$ (y * x)     it "is associative" $ do@@ -107,7 +111,7 @@   HSpec properties that each implementation of CanMulSameType should satisfy.  -} specCanMulSameType ::-  (Show t, ConvertibleExactly Integer t,+  (Show t, Arbitrary t, ConvertibleExactlyWithSample Integer t,    CanTestCertainly (EqCompareType t t), HasEqAsymmetric t t,    CanMulAsymmetric t t, MulType t t ~ t)    =>@@ -115,10 +119,13 @@ specCanMulSameType (T typeName :: T t) =   describe (printf "CanMulSameType %s" typeName) $ do     it "has product working over integers" $ do-      property $ \ (xsi :: [Integer]) ->-        (product $ (map convertExactly xsi :: [t])) ?==?$ (convertExactly (product xsi) :: t)+      property $ \ (xsi :: [Integer]) (sampleT :: t) ->+        (productWithSample sampleT $ (map (convertExactlyWithSample sampleT) xsi :: [t])) +        ?==?$ +        (convertExactlyWithSample sampleT (product xsi) :: t)     it "has product [] = 1" $ do-        (product ([] :: [t])) ?==?$ (convertExactly 1 :: t)+      property $ \ (sampleT :: t) ->+        (productWithSample sampleT ([] :: [t])) ?==?$ (convertExactlyWithSample sampleT 1 :: t)   where   infix 4 ?==?$   (?==?$) :: (HasEqCertainlyAsymmetric a b, Show a, Show b) => a -> b -> Property
src/Numeric/MixedTypes/Power.hs view
@@ -177,13 +177,13 @@ specCanPow (T typeName1 :: T t1) (T typeName2 :: T t2) =   describe (printf "CanPow %s %s" typeName1 typeName2) $ do     it "x^0 = 1" $ do-      property $ \ (x :: t1) ->-        let one = (convertExactly 1 :: t1) in-        let z = (convertExactly 0 :: t2) in+      property $ \ (x :: t1) (sampleT1 :: t1) (sampleT2 :: t2) ->+        let one = (convertExactlyWithSample sampleT1 1 :: t1) in+        let z = (convertExactlyWithSample sampleT2 0 :: t2) in         (x ^ z) ?==?$ one     it "x^1 = x" $ do-      property $ \ (x :: t1) ->-        let one = (convertExactly 1 :: t2) in+      property $ \ (x :: t1) (sampleT2 :: t2) ->+        let one = (convertExactlyWithSample sampleT2 1 :: t2) in         (x ^ one) ?==?$ x     it "x^(y+1) = x*x^y" $ do       property $ \ (x :: t1) (y :: t2) ->
src/Numeric/MixedTypes/Ring.hs view
@@ -42,7 +42,7 @@    HasEq t t,    HasEq t Integer, CanAddSubMulBy t Integer,    HasEq t Int, CanAddSubMulBy t Int,-   HasIntegers t) => Ring t+   HasIntegersWithSample t) => Ring t  instance Ring Integer instance Ring (CN Integer)
src/Numeric/MixedTypes/Round.hs view
@@ -255,8 +255,8 @@           let diffCeilingFloorX = ceiling x - floor x in           (0 ?<=? diffCeilingFloorX) .&&. (diffCeilingFloorX ?<=? 1)     it "holds floor x = round x = ceiling x for integers" $ do-      property $ \ (xi :: Integer) ->-        let x = convertExactly xi :: t in+      property $ \ (xi :: Integer) (sampleT :: t) ->+        let x = convertExactlyWithSample sampleT xi :: t in           (floor x !==!$ round x) .&&. (round x !==!$ ceiling x)   where   (?<=?$) :: (HasOrderCertainlyAsymmetric a b, Show a, Show b) => a -> b -> Property
src/Utils/Test/EnforceRange.hs view
@@ -33,7 +33,7 @@     (CanAddSubMulDivBy t Integer     , CanAddSameType t, CanSubSameType t, CanAbsSameType t     , CanDivIModIntegerSameType t-    , ConvertibleExactly b t+    , ConvertibleExactlyWithSample b t     , HasOrderCertainly t t)  {-| @@ -50,17 +50,17 @@     | l !<! b && b !<! u = b     | otherwise = (u+l)/2     where-    l = convertExactly l_ :: t-    u = convertExactly u_ :: t+    l = convertExactlyWithSample a l_ :: t+    u = convertExactlyWithSample a u_ :: t     b = l + ((abs a) `mod` (u-l)) enforceRange (Just l_, _) (a::t)     | l !<! a = a     | otherwise = (2*l-a+1)     where-    l = convertExactly l_ :: t+    l = convertExactlyWithSample a l_ :: t enforceRange (_, Just u_) (a::t)     | a !<! u = a     | otherwise = (2*u-a-1)     where-    u = convertExactly u_ :: t+    u = convertExactlyWithSample a u_ :: t enforceRange _ a = a