Skip to content

Commit

Permalink
Introduce clamp, extent and range
Browse files Browse the repository at this point in the history
  • Loading branch information
JamieBallingall committed Sep 29, 2022
1 parent fa3f258 commit 8109065
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 18 deletions.
16 changes: 15 additions & 1 deletion src/Data/Array/AtLeast.purs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ module Data.Array.ArrayAL
, append
, appendArray
, prependArray
, range
, concat
, intersperse

Expand Down Expand Up @@ -68,7 +69,7 @@ import Data.FastVect.FastVect as FV
import Data.Foldable (class Foldable)
import Data.FoldableWithIndex (class FoldableWithIndex)
import Data.FunctorWithIndex (class FunctorWithIndex)
import Data.Int.AtLeast (IntAL, fromInt')
import Data.Int.AtLeast (IntAL, fromInt', toInt)
import Data.Maybe (Maybe(Nothing, Just), fromJust)
import Data.Reflectable (class Reflectable, reflectType)
import Data.Semigroup.Foldable (class Foldable1, foldMap1DefaultL)
Expand Down Expand Up @@ -249,6 +250,19 @@ appendArray (ArrayAL xs) ys = ArrayAL $ xs <> ys
prependArray :: (n :: Int) (a :: Type). Array a -> ArrayAL n a -> ArrayAL n a
prependArray xs (ArrayAL ys) = ArrayAL $ xs <> ys

-- | Construct an `ArrayAL 1` of `IntAL min`, starting with the (type-level)
-- | minimum `min` and ending with the runtime value of the `IntAL min`
range
:: (min :: Int). Reflectable min Int => IntAL min -> ArrayAL 1 (IntAL min)
range i = ArrayAL $ toIntAL <$> values
where

toIntAL :: Int -> IntAL min
toIntAL j = unsafePartial $ fromInt' j

values :: Array Int
values = Array.range (reflectType (Proxy :: _ min)) (toInt i)

concat
:: (m :: Int) (n :: Int) (mn :: Int) (a :: Type)
. Compare (-1) m LT
Expand Down
58 changes: 41 additions & 17 deletions src/Data/Int/AtLeast.purs
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
module Data.Int.AtLeast
( IntAL -- Constructor not exported. Use fromInt or fromInt'
( IntAL -- Constructor not exported. Use fromInt, fromInt' or clamp
, fromInt
, fromInt'
, clamp
, toInt
, toNumber
, (%+%), plus
, (%-%), minus
, (%*%), times
, (%/%), quotient
, extent
, (%+%)
, plus
, (%-%)
, minus
, (%*%)
, times
, (%/%)
, quotient
, modulo
, remainder
, divide
Expand Down Expand Up @@ -54,34 +60,47 @@ instance Reflectable min Int => Enum (IntAL min) where
if n > reflectType (Proxy :: _ min) then Just (IntAL $ n - 1) else Nothing

instance Reflectable min Int => Show (IntAL min) where
show (IntAL i) = "IntAL " <> show (reflectType (Proxy :: _ min)) <> " " <> show i
show (IntAL i) = "IntAL " <> show (reflectType (Proxy :: _ min)) <> " " <>
show i

instance Reflectable min Int => Arbitrary (IntAL min) where
arbitrary =
let
n = reflectType (Proxy :: _ min)
in
IntAL <$> oneOf (NEA.cons'
( elements $ NEA.singleton n )
[ chooseInt (n + 1) (n + 10)
, chooseInt (n + 11) (n + 100)
, chooseInt (n + 101) (n + 10000)
])
IntAL <$> oneOf
( NEA.cons'
(elements $ NEA.singleton n)
[ chooseInt (n + 1) (n + 10)
, chooseInt (n + 11) (n + 100)
, chooseInt (n + 101) (n + 10000)
]
)

-- | Convert an `Int` to an `IntAL min`, returning `Nothing` if the runtime
-- | value of the input is smaller than `min`
fromInt :: (min :: Int). Reflectable min Int => Int -> Maybe (IntAL min)
fromInt i = if i >= reflectType (Proxy :: _ min) then Just (IntAL i) else Nothing
fromInt i =
if i >= reflectType (Proxy :: _ min) then Just (IntAL i) else Nothing

-- | A partial function, converting an `Int` to an `IntAL min`. Crashes at
-- | runtime if the runtime value of the input is smaller than `min`
fromInt'
:: (min :: Int). Reflectable min Int => Partial => Int -> IntAL min
fromInt' i =
if i >= reflectType (Proxy :: _ min) then IntAL i
else
crashWith $ "Cannot convert Int " <> show i <> " to IntAL " <>
show (reflectType (Proxy :: _ min))
let
minInt = reflectType (Proxy :: _ min)
in
if i >= minInt then IntAL i
else crashWith $
"Cannot convert Int " <> show i <> " to IntAL " <> show minInt

clamp :: (min :: Int). Reflectable min Int => Int -> IntAL min
clamp i =
let
minInt = reflectType (Proxy :: _ min)
in
if i >= minInt then IntAL i else IntAL minInt

-- | Convert an `IntAL` to an `Int`
toInt :: (min :: Int). IntAL min -> Int
Expand All @@ -91,6 +110,11 @@ toInt (IntAL i) = i
toNumber :: (min :: Int). IntAL min -> Number
toNumber (IntAL i) = Int.toNumber i

-- | Measure the distance between the runtime value of an `IntAL min` and the
-- | type-level minimum value `min`, as an IntAL 0
extent :: (min :: Int). Reflectable min Int => IntAL min -> IntAL 0
extent (IntAL i) = IntAL $ reflectType (Proxy :: _ min) - i

-- | Add two IntAL values with possibly different type-level minimums
plus
:: (min_i :: Int) (min_j :: Int) (min_sum :: Int)
Expand Down

0 comments on commit 8109065

Please sign in to comment.