Skip to content
This repository was archived by the owner on Mar 25, 2021. It is now read-only.

Commit 7b6a617

Browse files
authored
Merge pull request #16 from jacereda/master
Product instances in Bounded and Enum
2 parents 7b78a94 + 27cd01c commit 7b6a617

File tree

3 files changed

+95
-2
lines changed

3 files changed

+95
-2
lines changed

src/Data/Generic/Rep/Bounded.purs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ instance genericBottomArgument :: Bounded a => GenericBottom (Argument a) where
2323
instance genericBottomSum :: GenericBottom a => GenericBottom (Sum a b) where
2424
genericBottom' = Inl genericBottom'
2525

26+
instance genericBottomProduct :: (GenericBottom a, GenericBottom b) => GenericBottom (Product a b) where
27+
genericBottom' = Product genericBottom' genericBottom'
28+
2629
instance genericBottomConstructor :: GenericBottom a => GenericBottom (Constructor name a) where
2730
genericBottom' = Constructor genericBottom'
2831

@@ -38,6 +41,9 @@ instance genericTopArgument :: Bounded a => GenericTop (Argument a) where
3841
instance genericTopSum :: GenericTop b => GenericTop (Sum a b) where
3942
genericTop' = Inr genericTop'
4043

44+
instance genericTopProduct :: (GenericTop a, GenericTop b) => GenericTop (Product a b) where
45+
genericTop' = Product genericTop' genericTop'
46+
4147
instance genericTopConstructor :: GenericTop a => GenericTop (Constructor name a) where
4248
genericTop' = Constructor genericTop'
4349

src/Data/Generic/Rep/Enum.purs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module Data.Generic.Rep.Enum where
33
import Prelude
44

55
import Data.Enum (class BoundedEnum, class Enum, Cardinality(..), cardinality, fromEnum, pred, succ, toEnum)
6-
import Data.Generic.Rep (class Generic, Argument(..), Constructor(..), NoArguments(..), Sum(..), from, to)
6+
import Data.Generic.Rep (class Generic, Argument(..), Constructor(..), NoArguments(..), Product(..), Sum(..), from, to)
77
import Data.Generic.Rep.Bounded (class GenericBottom, class GenericTop, genericBottom', genericTop')
88
import Data.Maybe (Maybe(..))
99
import Data.Newtype (unwrap)
@@ -36,6 +36,15 @@ instance genericEnumSum :: (GenericEnum a, GenericTop a, GenericEnum b, GenericB
3636
Just a' -> Just (Inl a')
3737
Inr b -> Inr <$> genericSucc' b
3838

39+
instance genericEnumProduct :: (GenericEnum a, GenericTop a, GenericBottom a, GenericEnum b, GenericTop b, GenericBottom b) => GenericEnum (Product a b) where
40+
genericPred' (Product a b) = case genericPred' b of
41+
Just p -> Just $ Product a p
42+
Nothing -> flip Product genericTop' <$> genericPred' a
43+
genericSucc' (Product a b) = case genericSucc' b of
44+
Just s -> Just $ Product a s
45+
Nothing -> flip Product genericBottom' <$> genericSucc' a
46+
47+
3948
-- | A `Generic` implementation of the `pred` member from the `Enum` type class.
4049
genericPred :: forall a rep. Generic a rep => GenericEnum rep => a -> Maybe a
4150
genericPred = map to <<< genericPred' <<< from
@@ -79,6 +88,20 @@ instance genericBoundedEnumSum :: (GenericBoundedEnum a, GenericBoundedEnum b) =
7988
Inl a -> genericFromEnum' a
8089
Inr b -> genericFromEnum' b + unwrap (genericCardinality' :: Cardinality a)
8190

91+
92+
instance genericBoundedEnumProduct :: (GenericBoundedEnum a, GenericBoundedEnum b) => GenericBoundedEnum (Product a b) where
93+
genericCardinality' =
94+
Cardinality
95+
$ unwrap (genericCardinality' :: Cardinality a)
96+
* unwrap (genericCardinality' :: Cardinality b)
97+
genericToEnum' n = to genericCardinality'
98+
where to :: Cardinality b -> Maybe (Product a b)
99+
to (Cardinality cb) = Product <$> (genericToEnum' $ n `div` cb) <*> (genericToEnum' $ n `mod` cb)
100+
genericFromEnum' = from genericCardinality'
101+
where from :: Cardinality b -> (Product a b) -> Int
102+
from (Cardinality cb) (Product a b) = genericFromEnum' a * cb + genericFromEnum' b
103+
104+
82105
-- | A `Generic` implementation of the `cardinality` member from the
83106
-- | `BoundedEnum` type class.
84107
genericCardinality :: forall a rep. Generic a rep => GenericBoundedEnum rep => Cardinality a

test/Main.purs

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import Prelude
44

55
import Control.Monad.Eff (Eff)
66
import Control.Monad.Eff.Console (CONSOLE, log, logShow)
7-
import Data.Enum (class BoundedEnum, class Enum, Cardinality(..), cardinality, fromEnum, pred, succ, toEnum)
7+
import Data.Enum (class BoundedEnum, class Enum, Cardinality(..), cardinality, fromEnum, pred, succ, toEnum, enumFromTo)
88
import Data.Generic.Rep as G
99
import Data.Generic.Rep.Bounded as GBounded
1010
import Data.Generic.Rep.Enum as GEnum
@@ -68,6 +68,45 @@ instance boundedEnumOption :: BoundedEnum a => BoundedEnum (Option a) where
6868
toEnum = GEnum.genericToEnum
6969
fromEnum = GEnum.genericFromEnum
7070

71+
data Bit = Zero | One
72+
derive instance genericBit :: G.Generic Bit _
73+
instance eqBit :: Eq Bit where
74+
eq x y = GEq.genericEq x y
75+
instance ordBit :: Ord Bit where
76+
compare x y = GOrd.genericCompare x y
77+
instance showBit :: Show Bit where
78+
show x = GShow.genericShow x
79+
instance boundedBit :: Bounded Bit where
80+
bottom = GBounded.genericBottom
81+
top = GBounded.genericTop
82+
instance enumBit :: Enum Bit where
83+
pred = GEnum.genericPred
84+
succ = GEnum.genericSucc
85+
instance boundedEnumBit :: BoundedEnum Bit where
86+
cardinality = GEnum.genericCardinality
87+
toEnum = GEnum.genericToEnum
88+
fromEnum = GEnum.genericFromEnum
89+
90+
data Pair a b = Pair a b
91+
derive instance genericPair :: G.Generic (Pair a b) _
92+
instance eqPair :: (Eq a, Eq b) => Eq (Pair a b) where
93+
eq = GEq.genericEq
94+
instance ordPair :: (Ord a, Ord b) => Ord (Pair a b) where
95+
compare = GOrd.genericCompare
96+
instance showPair :: (Show a, Show b) => Show (Pair a b) where
97+
show = GShow.genericShow
98+
instance boundedPair :: (Bounded a, Bounded b) => Bounded (Pair a b) where
99+
bottom = GBounded.genericBottom
100+
top = GBounded.genericTop
101+
instance enumPair :: (Bounded a, Enum a, Bounded b, Enum b) => Enum (Pair a b) where
102+
pred = GEnum.genericPred
103+
succ = GEnum.genericSucc
104+
instance boundedEnumPair :: (BoundedEnum a, BoundedEnum b) => BoundedEnum (Pair a b) where
105+
cardinality = GEnum.genericCardinality
106+
toEnum = GEnum.genericToEnum
107+
fromEnum = GEnum.genericFromEnum
108+
109+
71110
main :: Eff (console :: CONSOLE, assert :: ASSERT) Unit
72111
main = do
73112
logShow (cons 1 (cons 2 Nil))
@@ -99,6 +138,12 @@ main = do
99138
log "Checking composite top"
100139
assert $ top == Some D
101140

141+
log "Checking product bottom"
142+
assert $ bottom == Pair Zero A :: Pair Bit SimpleBounded
143+
144+
log "Checking product top"
145+
assert $ top == Pair One D :: Pair Bit SimpleBounded
146+
102147
log "Checking simple pred bottom"
103148
assert $ pred (bottom :: SimpleBounded) == Nothing
104149

@@ -123,16 +168,35 @@ main = do
123168
log "Checking composite (succ =<< pred top)"
124169
assert $ (succ =<< pred top) == Just (Some D)
125170

171+
log "Checking product pred bottom"
172+
assert $ pred (bottom :: Pair Bit SimpleBounded) == Nothing
173+
174+
log "Checking product (pred =<< succ bottom)"
175+
assert $ (pred =<< succ (bottom :: Pair Bit SimpleBounded)) == Just (Pair Zero A)
176+
177+
log "Checking product succ top"
178+
assert $ succ (top :: Pair Bit SimpleBounded) == Nothing
179+
180+
log "Checking product (succ =<< pred top)"
181+
assert $ (succ =<< pred top) == Just (Pair One D)
182+
126183
log "Checking simple cardinality"
127184
assert $ (cardinality :: Cardinality SimpleBounded) == Cardinality 4
128185

129186
log "Checking composite cardinality"
130187
assert $ (cardinality :: Cardinality (Option SimpleBounded)) == Cardinality 5
131188

189+
log "Checking product cardinality"
190+
assert $ (cardinality :: Cardinality (Pair Bit SimpleBounded)) == Cardinality 8
191+
132192
log "Checking simple toEnum/fromEnum roundtrip"
133193
assert $ toEnum (fromEnum A) == Just A
134194
assert $ toEnum (fromEnum B) == Just B
135195

136196
log "Checking composite toEnum/fromEnum roundtrip"
137197
assert $ toEnum (fromEnum (None :: Option SimpleBounded)) == Just (None :: Option SimpleBounded)
138198
assert $ toEnum (fromEnum (Some A)) == Just (Some A)
199+
200+
log "Checking product toEnum/fromEnum roundtrip"
201+
assert $ let allPairs = enumFromTo bottom top :: Array (Pair Bit SimpleBounded)
202+
in toEnum <<< fromEnum <$> allPairs == Just <$> allPairs

0 commit comments

Comments
 (0)