Skip to content

Commit d7a0a8b

Browse files
authored
Fix laws (#32)
* Fix succ/pred laws * Add non-skipping laws * Use pred/succ instead of arithmetic * Use `any` and `all` per @paf31's suggestion * Add law explanations
1 parent fbdce5e commit d7a0a8b

File tree

1 file changed

+18
-6
lines changed

1 file changed

+18
-6
lines changed

src/Data/Enum.purs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,22 @@ derive newtype instance ordCardinality :: Ord (Cardinality a)
3939
-- | Type class for enumerations.
4040
-- |
4141
-- | Laws:
42-
-- | - `succ a > pred a`
43-
-- | - `pred a < succ a`
44-
-- | - `pred >=> succ >=> pred = pred`
45-
-- | - `succ >=> pred >=> succ = succ`
42+
-- | - Successor: `all (a < _) (succ a)`
43+
-- | - Predecessor: `all (_ < a) (pred a)`
44+
-- | - Succ retracts pred: `pred >=> succ >=> pred = pred`
45+
-- | - Pred retracts succ: `succ >=> pred >=> succ = succ`
46+
-- | - Non-skipping succ: `b <= a || any (_ <= b) (succ a)`
47+
-- | - Non-skipping pred: `a <= b || any (b <= _) (pred a)`
48+
-- |
49+
-- | The retraction laws can intuitively be understood as saying that `succ` is
50+
-- | the opposite of `pred`; if you apply `succ` and then `pred` to something,
51+
-- | you should end up with what you started with (although of course this
52+
-- | doesn't apply if you tried to `succ` the last value in an enumeration and
53+
-- | therefore got `Nothing` out). The non-skipping laws can intuitively be
54+
-- | understood as saying that `succ` shouldn't skip over any elements of your
55+
-- | type. For example, without the non-skipping laws, it would be permissible
56+
-- | to write an `Enum Int` instance where `succ x = Just (x+2)`, and similarly
57+
-- | `pred x = Just (x-2)`.
4658
class Ord a <= Enum a where
4759
succ :: a -> Maybe a
4860
pred :: a -> Maybe a
@@ -157,8 +169,8 @@ downFrom = unfoldr (map diag <<< pred)
157169
-- | - ```pred top >>= pred >>= pred ... pred [cardinality - 1 times] == bottom```
158170
-- | - ```forall a > bottom: pred a >>= succ == Just a```
159171
-- | - ```forall a < top: succ a >>= pred == Just a```
160-
-- | - ```forall a > bottom: fromEnum <$> pred a = Just (fromEnum a - 1)```
161-
-- | - ```forall a < top: fromEnum <$> succ a = Just (fromEnum a + 1)```
172+
-- | - ```forall a > bottom: fromEnum <$> pred a = pred (fromEnum a)```
173+
-- | - ```forall a < top: fromEnum <$> succ a = succ (fromEnum a)```
162174
-- | - ```e1 `compare` e2 == fromEnum e1 `compare` fromEnum e2```
163175
-- | - ```toEnum (fromEnum a) = Just a```
164176
class (Bounded a, Enum a) <= BoundedEnum a where

0 commit comments

Comments
 (0)