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

Commit 7d43c29

Browse files
committed
Add a newtype implementing generic instances for use with deriving via
1 parent aae27ba commit 7d43c29

File tree

14 files changed

+224
-167
lines changed

14 files changed

+224
-167
lines changed

src/Data/Generic/Rep.purs

Lines changed: 3 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,6 @@
11
module Data.Generic.Rep
2-
( class Generic
3-
, to
4-
, from
5-
, NoConstructors
6-
, NoArguments(..)
7-
, Sum(..)
8-
, Product(..)
9-
, Constructor(..)
10-
, Argument(..)
2+
( module X
113
) where
124

13-
import Data.Maybe (Maybe(..))
14-
15-
-- | A representation for types with no constructors.
16-
data NoConstructors
17-
18-
-- | A representation for constructors with no arguments.
19-
data NoArguments = NoArguments
20-
21-
-- | A representation for types with multiple constructors.
22-
data Sum a b = Inl a | Inr b
23-
24-
-- | A representation for constructors with multiple fields.
25-
data Product a b = Product a b
26-
27-
-- | A representation for constructors which includes the data constructor name
28-
-- | as a type-level string.
29-
newtype Constructor (name :: Symbol) a = Constructor a
30-
31-
-- | A representation for an argument in a data constructor.
32-
newtype Argument a = Argument a
33-
34-
-- | The `Generic` class asserts the existence of a type function from types
35-
-- | to their representations using the type constructors defined in this module.
36-
class Generic a rep | a -> rep where
37-
to :: rep -> a
38-
from :: a -> rep
39-
40-
instance genericMaybe
41-
:: Generic (Maybe a) (Sum (Constructor "Nothing" NoArguments)
42-
(Constructor "Just" (Argument a))) where
43-
to (Inl _) = Nothing
44-
to (Inr (Constructor (Argument a))) = Just a
45-
46-
from Nothing = Inl (Constructor NoArguments)
47-
from (Just a) = Inr (Constructor (Argument a))
48-
5+
import Data.Generic.Rep.Class (class Generic, Argument(..), Constructor(..), NoArguments(..), NoConstructors, Product(..), Sum(..), from, to) as X
6+
import Data.Generic.Rep.Derive (UsingGeneric(..)) as X

src/Data/Generic/Rep/Bounded.purs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ module Data.Generic.Rep.Bounded
77
, genericTop
88
) where
99

10-
import Data.Generic.Rep
10+
import Data.Generic.Rep.Class
1111

1212
import Data.Bounded (class Bounded, bottom, top)
1313

src/Data/Generic/Rep/Class.purs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
module Data.Generic.Rep.Class
2+
( class Generic
3+
, to
4+
, from
5+
, NoConstructors
6+
, NoArguments(..)
7+
, Sum(..)
8+
, Product(..)
9+
, Constructor(..)
10+
, Argument(..)
11+
) where
12+
13+
import Data.Maybe (Maybe(..))
14+
15+
-- | A representation for types with no constructors.
16+
data NoConstructors
17+
18+
-- | A representation for constructors with no arguments.
19+
data NoArguments = NoArguments
20+
21+
-- | A representation for types with multiple constructors.
22+
data Sum a b = Inl a | Inr b
23+
24+
-- | A representation for constructors with multiple fields.
25+
data Product a b = Product a b
26+
27+
-- | A representation for constructors which includes the data constructor name
28+
-- | as a type-level string.
29+
newtype Constructor (name :: Symbol) a = Constructor a
30+
31+
-- | A representation for an argument in a data constructor.
32+
newtype Argument a = Argument a
33+
34+
-- | The `Generic` class asserts the existence of a type function from types
35+
-- | to their representations using the type constructors defined in this module.
36+
class Generic a rep | a -> rep where
37+
to :: rep -> a
38+
from :: a -> rep
39+
40+
instance genericMaybe
41+
:: Generic (Maybe a) (Sum (Constructor "Nothing" NoArguments)
42+
(Constructor "Just" (Argument a))) where
43+
to (Inl _) = Nothing
44+
to (Inr (Constructor (Argument a))) = Just a
45+
46+
from Nothing = Inl (Constructor NoArguments)
47+
from (Just a) = Inr (Constructor (Argument a))

src/Data/Generic/Rep/Derive.purs

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
module Data.Generic.Rep.Derive where
2+
3+
import Prelude
4+
5+
import Data.Enum (class BoundedEnum, class Enum, Cardinality(..))
6+
import Data.Function (on)
7+
import Data.Generic.Rep.Bounded (class GenericBottom, class GenericTop, genericBottom, genericTop)
8+
import Data.Generic.Rep.Class (class Generic)
9+
import Data.Generic.Rep.Enum (class GenericBoundedEnum, class GenericEnum, genericCardinality, genericFromEnum, genericPred, genericSucc, genericToEnum)
10+
import Data.Generic.Rep.Eq (class GenericEq, genericEq)
11+
import Data.Generic.Rep.HeytingAlgebra (class GenericHeytingAlgebra, genericConj, genericDisj, genericFF, genericImplies, genericNot, genericTT)
12+
import Data.Generic.Rep.Monoid (class GenericMonoid, genericMempty)
13+
import Data.Generic.Rep.Ord (class GenericOrd, genericCompare)
14+
import Data.Generic.Rep.Ring (class GenericRing, genericSub)
15+
import Data.Generic.Rep.Semigroup (class GenericSemigroup, genericAppend)
16+
import Data.Generic.Rep.Semiring (class GenericSemiring, genericAdd, genericMul, genericOne, genericZero)
17+
import Data.Generic.Rep.Show (class GenericShow, genericShow)
18+
import Data.Newtype (class Newtype, over, over2, traverse, unwrap)
19+
20+
newtype UsingGeneric a = UsingGeneric a
21+
22+
derive instance newtypeUsingGeneric :: Newtype (UsingGeneric a) _
23+
24+
instance boundedUsingGeneric ::
25+
( Generic a rep
26+
, GenericBottom rep
27+
, GenericEq rep
28+
, GenericOrd rep
29+
, GenericTop rep
30+
) => Bounded (UsingGeneric a) where
31+
top = UsingGeneric genericTop
32+
bottom = UsingGeneric genericBottom
33+
34+
instance boundedEnumUsingGeneric ::
35+
( Generic a rep
36+
, GenericBottom rep
37+
, GenericBoundedEnum rep
38+
, GenericEnum rep
39+
, GenericEq rep
40+
, GenericOrd rep
41+
, GenericTop rep
42+
) => BoundedEnum (UsingGeneric a) where
43+
cardinality = Cardinality $ unwrap (genericCardinality :: Cardinality a)
44+
toEnum = genericToEnum >>> map UsingGeneric
45+
fromEnum = unwrap >>> genericFromEnum
46+
47+
instance enumUsingGeneric ::
48+
( Generic a rep
49+
, GenericEnum rep
50+
, GenericEq rep
51+
, GenericOrd rep
52+
) => Enum (UsingGeneric a) where
53+
succ = traverse UsingGeneric genericSucc
54+
pred = traverse UsingGeneric genericPred
55+
56+
instance eqUsingGeneric ::
57+
( Generic a rep
58+
, GenericEq rep
59+
) => Eq (UsingGeneric a) where
60+
eq = genericEq `on` unwrap
61+
62+
instance heytingAlgebraUsingGeneric ::
63+
( Generic a rep
64+
, GenericHeytingAlgebra rep
65+
) => HeytingAlgebra (UsingGeneric a) where
66+
ff = UsingGeneric genericFF
67+
tt = UsingGeneric genericTT
68+
implies = over2 UsingGeneric genericImplies
69+
conj = over2 UsingGeneric genericConj
70+
disj = over2 UsingGeneric genericDisj
71+
not = over UsingGeneric genericNot
72+
73+
instance monoidUsingGeneric ::
74+
( Generic a rep
75+
, GenericMonoid rep
76+
, GenericSemigroup rep
77+
) => Monoid (UsingGeneric a) where
78+
mempty = UsingGeneric genericMempty
79+
80+
instance ordUsingGeneric ::
81+
( Generic a rep
82+
, GenericEq rep
83+
, GenericOrd rep
84+
) => Ord (UsingGeneric a) where
85+
compare = genericCompare `on` unwrap
86+
87+
instance ringUsingGeneric ::
88+
( Generic a rep
89+
, GenericRing rep
90+
, GenericSemiring rep
91+
) => Ring (UsingGeneric a) where
92+
sub = over2 UsingGeneric genericSub
93+
94+
instance semigroupUsingGeneric ::
95+
( Generic a rep
96+
, GenericSemigroup rep
97+
) => Semigroup (UsingGeneric a) where
98+
append = over2 UsingGeneric genericAppend
99+
100+
instance semiringUsingGeneric ::
101+
( Generic a rep
102+
, GenericSemiring rep
103+
) => Semiring (UsingGeneric a) where
104+
add = over2 UsingGeneric genericAdd
105+
zero = UsingGeneric genericZero
106+
mul = over2 UsingGeneric genericMul
107+
one = UsingGeneric genericOne
108+
109+
instance showUsingGeneric ::
110+
( Generic a rep
111+
, GenericShow rep
112+
) => Show (UsingGeneric a) where
113+
show = unwrap >>> genericShow

src/Data/Generic/Rep/Enum.purs

Lines changed: 1 addition & 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(..), Product(..), Sum(..), from, to)
6+
import Data.Generic.Rep.Class (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)

src/Data/Generic/Rep/Eq.purs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ module Data.Generic.Rep.Eq
55
) where
66

77
import Prelude (class Eq, (==), (&&))
8-
import Data.Generic.Rep
8+
import Data.Generic.Rep.Class
99

1010
class GenericEq a where
1111
genericEq' :: a -> a -> Boolean

src/Data/Generic/Rep/HeytingAlgebra.purs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ module Data.Generic.Rep.HeytingAlgebra where
22

33
import Prelude
44

5-
import Data.Generic.Rep (class Generic, Argument(..), Constructor(..), NoArguments(..), Product(..), from, to)
5+
import Data.Generic.Rep.Class (class Generic, Argument(..), Constructor(..), NoArguments(..), Product(..), from, to)
66
import Data.HeytingAlgebra (ff, implies, tt)
77

88
class GenericHeytingAlgebra a where
@@ -67,4 +67,4 @@ genericDisj x y = to $ from x `genericDisj'` from y
6767

6868
-- | A `Generic` implementation of the `not` member from the `HeytingAlgebra` type class.
6969
genericNot :: forall a rep. Generic a rep => GenericHeytingAlgebra rep => a -> a
70-
genericNot x = to $ genericNot' (from x)
70+
genericNot x = to $ genericNot' (from x)

src/Data/Generic/Rep/Monoid.purs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ module Data.Generic.Rep.Monoid
55
) where
66

77
import Data.Monoid (class Monoid, mempty)
8-
import Data.Generic.Rep
8+
import Data.Generic.Rep.Class
99

1010
class GenericMonoid a where
1111
genericMempty' :: a

src/Data/Generic/Rep/Ord.purs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ module Data.Generic.Rep.Ord
55
) where
66

77
import Prelude (class Ord, compare, Ordering(..))
8-
import Data.Generic.Rep
8+
import Data.Generic.Rep.Class
99

1010
class GenericOrd a where
1111
genericCompare' :: a -> a -> Ordering

src/Data/Generic/Rep/Ring.purs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ module Data.Generic.Rep.Ring where
22

33
import Prelude
44

5-
import Data.Generic.Rep (class Generic, Argument(..), Constructor(..), NoArguments(..), Product(..), from, to)
5+
import Data.Generic.Rep.Class (class Generic, Argument(..), Constructor(..), NoArguments(..), Product(..), from, to)
66

77
class GenericRing a where
88
genericSub' :: a -> a -> a
@@ -21,4 +21,4 @@ instance genericRingConstructor :: GenericRing a => GenericRing (Constructor nam
2121

2222
-- | A `Generic` implementation of the `sub` member from the `Ring` type class.
2323
genericSub :: forall a rep. Generic a rep => GenericRing rep => a -> a -> a
24-
genericSub x y = to $ from x `genericSub'` from y
24+
genericSub x y = to $ from x `genericSub'` from y

src/Data/Generic/Rep/Semigroup.purs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ module Data.Generic.Rep.Semigroup
55
) where
66

77
import Prelude (class Semigroup, append)
8-
import Data.Generic.Rep
8+
import Data.Generic.Rep.Class
99

1010
class GenericSemigroup a where
1111
genericAppend' :: a -> a -> a

src/Data/Generic/Rep/Semiring.purs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ module Data.Generic.Rep.Semiring where
22

33
import Prelude
44

5-
import Data.Generic.Rep (class Generic, Argument(..), Constructor(..), NoArguments(..), Product(..), from, to)
5+
import Data.Generic.Rep.Class (class Generic, Argument(..), Constructor(..), NoArguments(..), Product(..), from, to)
66

77
class GenericSemiring a where
88
genericAdd' :: a -> a -> a
@@ -48,4 +48,4 @@ genericAdd x y = to $ from x `genericAdd'` from y
4848

4949
-- | A `Generic` implementation of the `mul` member from the `Semiring` type class.
5050
genericMul :: forall a rep. Generic a rep => GenericSemiring rep => a -> a -> a
51-
genericMul x y = to $ from x `genericMul'` from y
51+
genericMul x y = to $ from x `genericMul'` from y

src/Data/Generic/Rep/Show.purs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ module Data.Generic.Rep.Show
88

99
import Prelude (class Show, show, (<>))
1010
import Data.Foldable (intercalate)
11-
import Data.Generic.Rep
11+
import Data.Generic.Rep.Class
1212
import Data.Symbol (class IsSymbol, SProxy(..), reflectSymbol)
1313

1414
class GenericShow a where

0 commit comments

Comments
 (0)