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

Commit 52c0d41

Browse files
committed
Add GenericEnum and GenericBoundedEnum
1 parent e297aeb commit 52c0d41

File tree

2 files changed

+99
-3
lines changed

2 files changed

+99
-3
lines changed

bower.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@
1212
"url": "git://github.com/purescript/purescript-generics-rep.git"
1313
},
1414
"dependencies": {
15-
"purescript-prelude": "^3.0.0",
15+
"purescript-enums": "^3.2.1",
16+
"purescript-foldable-traversable": "^3.0.0",
1617
"purescript-monoid": "^3.0.0",
17-
"purescript-symbols": "^3.0.0",
18-
"purescript-foldable-traversable": "^3.0.0"
18+
"purescript-prelude": "^3.0.0",
19+
"purescript-symbols": "^3.0.0"
1920
},
2021
"devDependencies": {
2122
"purescript-console": "^3.0.0"

src/Data/Generic/Rep/Enum.purs

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
module Data.Generic.Rep.Enum where
2+
3+
import Prelude
4+
5+
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)
7+
import Data.Generic.Rep.Bounded (class GenericBottom, class GenericTop, genericBottom', genericTop')
8+
import Data.Maybe (Maybe(..))
9+
import Data.Newtype (unwrap)
10+
11+
class GenericEnum a where
12+
genericPred' :: a -> Maybe a
13+
genericSucc' :: a -> Maybe a
14+
15+
instance genericEnumNoArguments :: GenericEnum NoArguments where
16+
genericPred' _ = Nothing
17+
genericSucc' _ = Nothing
18+
19+
instance genericEnumArgument :: Enum a => GenericEnum (Argument a) where
20+
genericPred' (Argument a) = Argument <$> pred a
21+
genericSucc' (Argument a) = Argument <$> succ a
22+
23+
instance genericEnumConstructor :: GenericEnum a => GenericEnum (Constructor name a) where
24+
genericPred' (Constructor a) = Constructor <$> genericPred' a
25+
genericSucc' (Constructor a) = Constructor <$> genericSucc' a
26+
27+
instance genericEnumSum :: (GenericEnum a, GenericTop a, GenericEnum b, GenericBottom b) => GenericEnum (Sum a b) where
28+
genericPred' = case _ of
29+
Inl a -> Inl <$> genericPred' a
30+
Inr b -> case genericPred' b of
31+
Nothing -> Just (Inl genericTop')
32+
Just b' -> Just (Inr b')
33+
genericSucc' = case _ of
34+
Inl a -> case genericSucc' a of
35+
Nothing -> Just (Inr genericBottom')
36+
Just a' -> Just (Inl a')
37+
Inr b -> Inr <$> genericSucc' b
38+
39+
-- | A `Generic` implementation of the `pred` member from the `Enum` type class.
40+
genericPred :: forall a rep. Generic a rep => GenericEnum rep => a -> Maybe a
41+
genericPred = map to <<< genericPred' <<< from
42+
43+
-- | A `Generic` implementation of the `succ` member from the `Enum` type class.
44+
genericSucc :: forall a rep. Generic a rep => GenericEnum rep => a -> Maybe a
45+
genericSucc = map to <<< genericSucc' <<< from
46+
47+
class GenericBoundedEnum a where
48+
genericCardinality' :: Cardinality a
49+
genericToEnum' :: Int -> Maybe a
50+
genericFromEnum' :: a -> Int
51+
52+
instance genericBoundedEnumNoArguments :: GenericBoundedEnum NoArguments where
53+
genericCardinality' = Cardinality 1
54+
genericToEnum' i = if i == 0 then Just NoArguments else Nothing
55+
genericFromEnum' _ = 0
56+
57+
instance genericBoundedEnumArgument :: BoundedEnum a => GenericBoundedEnum (Argument a) where
58+
genericCardinality' = Cardinality (unwrap (cardinality :: Cardinality a))
59+
genericToEnum' i = Argument <$> toEnum i
60+
genericFromEnum' (Argument a) = fromEnum a
61+
62+
instance genericBoundedEnumConstructor :: GenericBoundedEnum a => GenericBoundedEnum (Constructor name a) where
63+
genericCardinality' = Cardinality (unwrap (genericCardinality' :: Cardinality a))
64+
genericToEnum' i = Constructor <$> genericToEnum' i
65+
genericFromEnum' (Constructor a) = genericFromEnum' a
66+
67+
instance genericBoundedEnumSum :: (GenericBoundedEnum a, GenericBoundedEnum b) => GenericBoundedEnum (Sum a b) where
68+
genericCardinality' =
69+
Cardinality
70+
$ unwrap (genericCardinality' :: Cardinality a)
71+
+ unwrap (genericCardinality' :: Cardinality b)
72+
genericToEnum' n = to genericCardinality'
73+
where
74+
to :: Cardinality a -> Maybe (Sum a b)
75+
to (Cardinality ca)
76+
| n >= 0 && n < ca = Inl <$> genericToEnum' n
77+
| otherwise = Inr <$> genericToEnum' (n - ca)
78+
genericFromEnum' = case _ of
79+
Inl a -> genericFromEnum' a
80+
Inr b -> genericFromEnum' b + unwrap (genericCardinality' :: Cardinality a)
81+
82+
-- | A `Generic` implementation of the `cardinality` member from the
83+
-- | `BoundedEnum` type class.
84+
genericCardinality :: forall a rep. Generic a rep => GenericBoundedEnum rep => Cardinality a
85+
genericCardinality = Cardinality (unwrap (genericCardinality' :: Cardinality rep))
86+
87+
-- | A `Generic` implementation of the `toEnum` member from the `BoundedEnum`
88+
-- | type class.
89+
genericToEnum :: forall a rep. Generic a rep => GenericBoundedEnum rep => Int -> Maybe a
90+
genericToEnum = map to <<< genericToEnum'
91+
92+
-- | A `Generic` implementation of the `fromEnum` member from the `BoundedEnum`
93+
-- | type class.
94+
genericFromEnum :: forall a rep. Generic a rep => GenericBoundedEnum rep => a -> Int
95+
genericFromEnum = genericFromEnum' <<< from

0 commit comments

Comments
 (0)