From 9917c402e96a501aebbdd5bcdfcefa4bd25a6602 Mon Sep 17 00:00:00 2001 From: Matthew Leon Date: Mon, 6 Nov 2017 17:48:38 -0500 Subject: [PATCH] more efficient genBoundedEnum Should reduce time and space complexity to that of chooseInt for most BoundedEnum instances. --- src/Data/Enum/Gen.purs | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/Data/Enum/Gen.purs b/src/Data/Enum/Gen.purs index 86caebd..5e3acc8 100644 --- a/src/Data/Enum/Gen.purs +++ b/src/Data/Enum/Gen.purs @@ -2,17 +2,24 @@ module Data.Enum.Gen where import Prelude -import Control.Monad.Gen (class MonadGen, elements) -import Data.Enum (class BoundedEnum, succ, enumFromTo) -import Data.Maybe (Maybe(..)) +import Control.Monad.Gen (class MonadGen, chooseInt, elements) +import Data.Enum (class BoundedEnum, Cardinality, cardinality, enumFromTo, fromEnum, succ, toEnum) +import Data.Maybe (Maybe(..), fromJust) +import Data.Newtype (unwrap) import Data.NonEmpty ((:|)) +import Partial.Unsafe (unsafePartial) -- | Create a random generator for a finite enumeration. genBoundedEnum :: forall m a. MonadGen m => BoundedEnum a => m a genBoundedEnum = - case succ bottom of - Just a → - let possibilities = enumFromTo a top :: Array a - in elements (bottom :| possibilities) - Nothing → - pure bottom + let topInt = fromEnum (top :: a) + bottomInt = fromEnum (bottom :: a) + enumRange = topInt - bottomInt + in if enumRange == unwrap (cardinality :: Cardinality a) + then unsafePartial $ fromJust <<< toEnum <$> chooseInt bottomInt topInt + else case succ bottom of + Just a → + let possibilities = enumFromTo a top :: Array a + in elements (bottom :| possibilities) + Nothing → + pure bottom