Skip to content

Commit 958f7fb

Browse files
committed
Merge pull request #1 from jdegoes/ready/sane-enums
change structure & add laws for enums
2 parents 28e2a45 + 0af1c67 commit 958f7fb

File tree

3 files changed

+114
-15
lines changed

3 files changed

+114
-15
lines changed

README.md

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,35 @@
22

33
## Module Data.Enum
44

5+
### Types
6+
7+
newtype Cardinality a where
8+
Cardinality :: Number -> Cardinality a
9+
10+
511
### Type Classes
612

7-
class Enum a where
8-
toEnum :: Prim.Number -> Maybe a
9-
fromEnum :: a -> Prim.Number
13+
class (Ord a) <= Enum a where
14+
cardinality :: Cardinality a
15+
firstEnum :: a
16+
lastEnum :: a
17+
succ :: a -> Maybe a
18+
pred :: a -> Maybe a
19+
20+
21+
### Type Class Instances
22+
23+
instance enumBoolean :: Enum Boolean
24+
25+
instance enumMaybe :: (Enum a) => Enum (Maybe a)
26+
27+
instance enumTuple :: (Enum a, Enum b) => Enum (Tuple a b)
1028

1129

1230
### Values
1331

14-
pred :: forall a. (Enum a) => a -> Maybe a
32+
fromEnum :: forall a. (Enum a) => a -> Number
33+
34+
runCardinality :: forall a. Cardinality a -> Number
1535

16-
succ :: forall a. (Enum a) => a -> Maybe a
36+
toEnum :: forall a. (Enum a) => Number -> Maybe a

bower.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"package.json"
1919
],
2020
"dependencies": {
21-
"purescript-maybe": "*"
21+
"purescript-maybe": "*",
22+
"purescript-tuples": "*"
2223
}
2324
}

src/Data/Enum.purs

Lines changed: 87 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,91 @@
1-
module Data.Enum where
1+
module Data.Enum
2+
( Enum
3+
, Cardinality(..)
4+
, fromEnum
5+
, runCardinality
6+
, toEnum
7+
) where
28

3-
import Data.Maybe
9+
import Data.Maybe
10+
import Data.Tuple
11+
import Data.Maybe.Unsafe
412

5-
class Enum a where
6-
toEnum :: Number -> Maybe a
7-
fromEnum :: a -> Number
13+
newtype Cardinality a = Cardinality Number
814

9-
succ :: forall a. (Enum a) => a -> Maybe a
10-
succ x = toEnum (fromEnum x + 1)
15+
runCardinality :: forall a. Cardinality a -> Number
16+
runCardinality (Cardinality a) = a
1117

12-
pred :: forall a. (Enum a) => a -> Maybe a
13-
pred x = toEnum (fromEnum x - 1)
18+
-- | Type class for enumerations. This should not be considered a part of a
19+
-- | numeric hierarchy, ala Haskell. Rather, this is a type class for small,
20+
-- | ordered sum types with statically-determined cardinality and the ability
21+
-- | to easily compute successor and predecessor elements. e.g. DayOfWeek, etc.
22+
-- |
23+
-- | Laws:
24+
-- | succ firstEnum >>= succ >>= succ ... succ [cardinality times] == lastEnum
25+
-- | pred lastEnum >>= pred >>= pred ... pred [cardinality times] == firstEnum
26+
-- |
27+
-- | Just $ e1 `compare` e2 == fromEnum e1 `compare` fromEnum e2
28+
-- |
29+
-- | for all a > firstEnum: pred a >>= succ == Just a
30+
-- | for all a < lastEnum: succ a >>= pred == Just a
31+
class (Ord a) <= Enum a where
32+
cardinality :: Cardinality a
33+
34+
firstEnum :: a
35+
36+
lastEnum :: a
37+
38+
succ :: a -> Maybe a
39+
40+
pred :: a -> Maybe a
41+
42+
toEnum :: forall a. (Enum a) => Number -> Maybe a
43+
toEnum n | n < 0 = Nothing
44+
toEnum 0 = Just firstEnum
45+
toEnum n = toEnum (n - 1) >>= succ
46+
47+
fromEnum :: forall a. (Enum a) => a -> Number
48+
fromEnum e = maybe 0 ((+) 1 <<< fromEnum) (pred e)
49+
50+
maybeCardinality :: forall a. (Enum a) => Cardinality a -> Cardinality (Maybe a)
51+
maybeCardinality c = Cardinality $ 1 + (runCardinality c)
52+
53+
instance enumMaybe :: (Enum a) => Enum (Maybe a) where
54+
cardinality = maybeCardinality cardinality
55+
56+
firstEnum = Nothing
57+
58+
lastEnum = Just $ lastEnum
59+
60+
succ Nothing = Just $ firstEnum
61+
succ (Just a) = Just <$> succ a
62+
63+
pred Nothing = Nothing
64+
pred (Just a) = Just <$> pred a
65+
66+
instance enumBoolean :: Enum Boolean where
67+
cardinality = Cardinality 2
68+
69+
firstEnum = false
70+
71+
lastEnum = true
72+
73+
succ false = Just true
74+
succ _ = Nothing
75+
76+
pred true = Just false
77+
pred _ = Nothing
78+
79+
instance enumTuple :: (Enum a, Enum b) => Enum (Tuple a b) where
80+
cardinality = tupleCardinality cardinality cardinality
81+
82+
firstEnum = Tuple firstEnum firstEnum
83+
84+
lastEnum = Tuple lastEnum lastEnum
85+
86+
succ (Tuple a b) = maybe (flip Tuple firstEnum <$> succ a) (Just <<< Tuple a) (succ b)
87+
88+
pred (Tuple a b) = maybe (flip Tuple firstEnum <$> pred a) (Just <<< Tuple a) (pred b)
89+
90+
tupleCardinality :: forall a b. (Enum a, Enum b) => Cardinality a -> Cardinality b -> Cardinality (Tuple a b)
91+
tupleCardinality l r = Cardinality $ (runCardinality l) * (runCardinality r)

0 commit comments

Comments
 (0)