From 8110a90e2feb9e86e33c3c40c7462ce4168c5f05 Mon Sep 17 00:00:00 2001 From: Liam Goodacre Date: Thu, 10 Nov 2016 21:24:29 +0000 Subject: [PATCH] Fix stack overflow in BoundedEnum (Either _ _) The definition of `toEnum` in the `BoundedEnum (Either _ _)` instance eagerly depended on its own instance. Hid the recursion behind a lambda. Added a regression test for the instance. --- src/Data/Enum.purs | 6 +++--- test/Test/Data/Enum.purs | 14 +++++++++++++- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/Data/Enum.purs b/src/Data/Enum.purs index 2939698..a639be7 100644 --- a/src/Data/Enum.purs +++ b/src/Data/Enum.purs @@ -203,10 +203,10 @@ instance boundedEnumEither :: (BoundedEnum a, BoundedEnum b) => BoundedEnum (Eit Cardinality $ unwrap (cardinality :: Cardinality a) + unwrap (cardinality :: Cardinality b) - toEnum = to cardinality cardinality + toEnum n = to cardinality cardinality where - to :: Cardinality a -> Cardinality (Either a b) -> Int -> Maybe (Either a b) - to (Cardinality ca) (Cardinality cab) n + to :: Cardinality a -> Cardinality (Either a b) -> Maybe (Either a b) + to (Cardinality ca) (Cardinality cab) | n >= 0 && n < ca = Left <$> toEnum n | n >= ca && n < cab = Right <$> toEnum (n - ca) | otherwise = Nothing diff --git a/test/Test/Data/Enum.purs b/test/Test/Data/Enum.purs index 52b413f..d25839a 100644 --- a/test/Test/Data/Enum.purs +++ b/test/Test/Data/Enum.purs @@ -5,10 +5,12 @@ import Prelude import Control.Monad.Eff (Eff) import Control.Monad.Eff.Console (CONSOLE, log) +import Data.Newtype (unwrap) import Data.Enum (class Enum, class BoundedEnum, defaultToEnum, defaultFromEnum, defaultCardinality, enumFromTo, enumFromThenTo, upFrom, - downFrom, toEnum) + downFrom, toEnum, fromEnum, Cardinality, cardinality) import Data.Maybe (Maybe(..)) +import Data.Either (Either(..)) import Test.Assert (ASSERT, assert) @@ -70,3 +72,13 @@ testEnum = do assert $ toEnum 1 == Just (Just false) :: Maybe (Maybe Boolean) assert $ toEnum 2 == Just (Just true) :: Maybe (Maybe Boolean) assert $ toEnum 3 == Nothing :: Maybe (Maybe Boolean) + + log "BoundedEnum (Either _ _)" + assert $ unwrap (cardinality :: Cardinality (Either Boolean Boolean)) == 4 + assert $ toEnum 0 == Just (Left false :: Either Boolean T) + assert $ toEnum 1 == Just (Left true :: Either Boolean T) + assert $ toEnum 3 == Just (Right B :: Either Boolean T) + assert $ fromEnum (Left false :: Either Boolean T) == 0 + assert $ fromEnum (Left true :: Either Boolean T) == 1 + assert $ fromEnum (Right B :: Either Boolean T) == 3 +