From 4433916be13eda878784da0ad84bd247923e25e3 Mon Sep 17 00:00:00 2001 From: Phil Freeman Date: Sat, 1 Oct 2016 12:53:01 -0700 Subject: [PATCH 01/33] first commit --- src/Data/Generic/Rep.purs | 185 ++++++++++++++++++++++++++++++++++++++ test/Main.purs | 31 +++++++ 2 files changed, 216 insertions(+) create mode 100644 src/Data/Generic/Rep.purs create mode 100644 test/Main.purs diff --git a/src/Data/Generic/Rep.purs b/src/Data/Generic/Rep.purs new file mode 100644 index 00000000..e695bbd1 --- /dev/null +++ b/src/Data/Generic/Rep.purs @@ -0,0 +1,185 @@ +module Data.Generic.Rep + ( class Generic + , to + , from + , NoConstructors + , NoArguments(..) + , Sum(..) + , Product(..) + , Constructor(..) + , Argument(..) + , Rec(..) + , Field(..) + , class GenericEq + , genericEq' + , genericEq + , class GenericOrd + , genericCompare' + , genericCompare + , class GenericSemigroup + , genericAppend' + , genericAppend + , class GenericMonoid + , genericMempty' + , genericMempty + ) where + +import Prelude + +import Data.Monoid (class Monoid, mempty) + +-- | A representation for types with no constructors. +data NoConstructors + +-- | A representation for constructors with no arguments. +data NoArguments = NoArguments + +-- | A representation for types with multiple constructors. +data Sum a b = Inl a | Inr b + +-- | A representation for constructors with multiple fields. +data Product a b = Product a b + +-- | A representation for constructors which includes the data constructor name +-- | as a type-level string. +newtype Constructor (name :: Symbol) a = Constructor a + +-- | A representation for an argument in a data constructor. +newtype Argument a = Argument a + +-- | A representation for records. +newtype Rec fields = Rec fields + +-- | A representation for a record field which includes the field name +-- | as a type-level string. +newtype Field (field :: Symbol) a = Field a + +-- | The `Generic` class asserts the existence of a type function from types +-- | to their representations using the type constructors defined in this module. +class Generic a rep | a -> rep where + to :: rep -> a + from :: a -> rep + +class GenericEq a where + genericEq' :: a -> a -> Boolean + +instance genericEqNoConstructors :: GenericEq NoConstructors where + genericEq' _ _ = true + +instance genericEqNoArguments :: GenericEq NoArguments where + genericEq' _ _ = true + +instance genericEqSum :: (GenericEq a, GenericEq b) => GenericEq (Sum a b) where + genericEq' (Inl a1) (Inl a2) = genericEq' a1 a2 + genericEq' (Inr b1) (Inr b2) = genericEq' b1 b2 + genericEq' _ _ = false + +instance genericEqProduct :: (GenericEq a, GenericEq b) => GenericEq (Product a b) where + genericEq' (Product a1 b1) (Product a2 b2) = genericEq' a1 a2 && genericEq' b1 b2 + +instance genericEqConstructor :: GenericEq a => GenericEq (Constructor name a) where + genericEq' (Constructor a1) (Constructor a2) = genericEq' a1 a2 + +instance genericEqArgument :: Eq a => GenericEq (Argument a) where + genericEq' (Argument a1) (Argument a2) = a1 == a2 + +instance genericEqRec :: GenericEq a => GenericEq (Rec a) where + genericEq' (Rec a1) (Rec a2) = genericEq' a1 a2 + +instance genericEqField :: GenericEq a => GenericEq (Field name a) where + genericEq' (Field a1) (Field a2) = genericEq' a1 a2 + +-- | A `Generic` implementation of the `eq` member from the `Eq` type class. +genericEq :: forall a rep. (Generic a rep, GenericEq rep) => a -> a -> Boolean +genericEq x y = genericEq' (from x) (from y) + +class GenericOrd a where + genericCompare' :: a -> a -> Ordering + +instance genericOrdNoConstructors :: GenericOrd NoConstructors where + genericCompare' _ _ = EQ + +instance genericOrdNoArguments :: GenericOrd NoArguments where + genericCompare' _ _ = EQ + +instance genericOrdSum :: (GenericOrd a, GenericOrd b) => GenericOrd (Sum a b) where + genericCompare' (Inl a1) (Inl a2) = genericCompare' a1 a2 + genericCompare' (Inr b1) (Inr b2) = genericCompare' b1 b2 + genericCompare' (Inl b1) (Inr b2) = LT + genericCompare' (Inr b1) (Inl b2) = GT + +instance genericOrdProduct :: (GenericOrd a, GenericOrd b) => GenericOrd (Product a b) where + genericCompare' (Product a1 b1) (Product a2 b2) = + case genericCompare' a1 a2 of + EQ -> genericCompare' b1 b2 + other -> other + +instance genericOrdConstructor :: GenericOrd a => GenericOrd (Constructor name a) where + genericCompare' (Constructor a1) (Constructor a2) = genericCompare' a1 a2 + +instance genericOrdArgument :: Ord a => GenericOrd (Argument a) where + genericCompare' (Argument a1) (Argument a2) = compare a1 a2 + +instance genericOrdRec :: GenericOrd a => GenericOrd (Rec a) where + genericCompare' (Rec a1) (Rec a2) = genericCompare' a1 a2 + +instance genericOrdField :: GenericOrd a => GenericOrd (Field name a) where + genericCompare' (Field a1) (Field a2) = genericCompare' a1 a2 + +-- | A `Generic` implementation of the `compare` member from the `Ord` type class. +genericCompare :: forall a rep. (Generic a rep, GenericOrd rep) => a -> a -> Ordering +genericCompare x y = genericCompare' (from x) (from y) + +class GenericSemigroup a where + genericAppend' :: a -> a -> a + +instance genericSemigroupNoConstructors :: GenericSemigroup NoConstructors where + genericAppend' a _ = a + +instance genericSemigroupNoArguments :: GenericSemigroup NoArguments where + genericAppend' a _ = a + +instance genericSemigroupProduct :: (GenericSemigroup a, GenericSemigroup b) => GenericSemigroup (Product a b) where + genericAppend' (Product a1 b1) (Product a2 b2) = + Product (genericAppend' a1 a2) (genericAppend' b1 b2) + +instance genericSemigroupConstructor :: GenericSemigroup a => GenericSemigroup (Constructor name a) where + genericAppend' (Constructor a1) (Constructor a2) = Constructor (genericAppend' a1 a2) + +instance genericSemigroupArgument :: Semigroup a => GenericSemigroup (Argument a) where + genericAppend' (Argument a1) (Argument a2) = Argument (append a1 a2) + +instance genericSemigroupRec :: GenericSemigroup a => GenericSemigroup (Rec a) where + genericAppend' (Rec a1) (Rec a2) = Rec (genericAppend' a1 a2) + +instance genericSemigroupField :: GenericSemigroup a => GenericSemigroup (Field name a) where + genericAppend' (Field a1) (Field a2) = Field (genericAppend' a1 a2) + +-- | A `Generic` implementation of the `append` member from the `Semigroup` type class. +genericAppend :: forall a rep. (Generic a rep, GenericSemigroup rep) => a -> a -> a +genericAppend x y = to (genericAppend' (from x) (from y)) + +class GenericMonoid a where + genericMempty' :: a + +instance genericMonoidNoArguments :: GenericMonoid NoArguments where + genericMempty' = NoArguments + +instance genericMonoidProduct :: (GenericMonoid a, GenericMonoid b) => GenericMonoid (Product a b) where + genericMempty' = Product genericMempty' genericMempty' + +instance genericMonoidConstructor :: GenericMonoid a => GenericMonoid (Constructor name a) where + genericMempty' = Constructor genericMempty' + +instance genericMonoidArgument :: Monoid a => GenericMonoid (Argument a) where + genericMempty' = Argument mempty + +instance genericMonoidRec :: GenericMonoid a => GenericMonoid (Rec a) where + genericMempty' = Rec genericMempty' + +instance genericMonoidField :: GenericMonoid a => GenericMonoid (Field name a) where + genericMempty' = Field genericMempty' + +-- | A `Generic` implementation of the `mempty` member from the `Monoid` type class. +genericMempty :: forall a rep. (Generic a rep, GenericMonoid rep) => a +genericMempty = to genericMempty' diff --git a/test/Main.purs b/test/Main.purs new file mode 100644 index 00000000..cccaf5f0 --- /dev/null +++ b/test/Main.purs @@ -0,0 +1,31 @@ +module Test.Main where + +import Prelude +import Control.Monad.Eff (Eff) +import Control.Monad.Eff.Console (CONSOLE, logShow) +import Data.Generic.Rep as G + +data List a = Nil | Cons a (List a) + +instance genericList :: G.Generic (List a) + (G.Sum (G.Constructor "Nil" G.NoArguments) + (G.Constructor "Cons" (G.Product (G.Argument a) + (G.Argument (List a))))) where + to (G.Inl (G.Constructor G.NoArguments)) = Nil + to (G.Inr (G.Constructor (G.Product (G.Argument x) (G.Argument xs)))) = Cons x xs + from Nil = G.Inl (G.Constructor G.NoArguments) + from (Cons x xs) = G.Inr (G.Constructor (G.Product (G.Argument x) (G.Argument xs))) + +instance eqList :: Eq a => Eq (List a) where + eq x y = G.genericEq x y + +instance ordList :: Ord a => Ord (List a) where + compare x y = G.genericCompare x y + +main :: Eff (console :: CONSOLE) Unit +main = do + logShow (Cons 1 (Cons 2 Nil) == Cons 1 (Cons 2 Nil)) + logShow (Cons 1 (Cons 2 Nil) == Cons 1 Nil) + + logShow (Cons 1 (Cons 2 Nil) `compare` Cons 1 (Cons 2 Nil)) + logShow (Cons 1 (Cons 2 Nil) `compare` Cons 1 Nil) From 98f28b47ea927656a150559bb9e84c5bfd231e9d Mon Sep 17 00:00:00 2001 From: Phil Freeman Date: Mon, 3 Oct 2016 21:07:55 -0700 Subject: [PATCH 02/33] Fix instances for record fields --- src/Data/Generic/Rep.purs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Data/Generic/Rep.purs b/src/Data/Generic/Rep.purs index e695bbd1..a1acc5b9 100644 --- a/src/Data/Generic/Rep.purs +++ b/src/Data/Generic/Rep.purs @@ -86,8 +86,8 @@ instance genericEqArgument :: Eq a => GenericEq (Argument a) where instance genericEqRec :: GenericEq a => GenericEq (Rec a) where genericEq' (Rec a1) (Rec a2) = genericEq' a1 a2 -instance genericEqField :: GenericEq a => GenericEq (Field name a) where - genericEq' (Field a1) (Field a2) = genericEq' a1 a2 +instance genericEqField :: Eq a => GenericEq (Field name a) where + genericEq' (Field a1) (Field a2) = a1 == a2 -- | A `Generic` implementation of the `eq` member from the `Eq` type class. genericEq :: forall a rep. (Generic a rep, GenericEq rep) => a -> a -> Boolean @@ -123,8 +123,8 @@ instance genericOrdArgument :: Ord a => GenericOrd (Argument a) where instance genericOrdRec :: GenericOrd a => GenericOrd (Rec a) where genericCompare' (Rec a1) (Rec a2) = genericCompare' a1 a2 -instance genericOrdField :: GenericOrd a => GenericOrd (Field name a) where - genericCompare' (Field a1) (Field a2) = genericCompare' a1 a2 +instance genericOrdField :: Ord a => GenericOrd (Field name a) where + genericCompare' (Field a1) (Field a2) = compare a1 a2 -- | A `Generic` implementation of the `compare` member from the `Ord` type class. genericCompare :: forall a rep. (Generic a rep, GenericOrd rep) => a -> a -> Ordering @@ -152,8 +152,8 @@ instance genericSemigroupArgument :: Semigroup a => GenericSemigroup (Argument a instance genericSemigroupRec :: GenericSemigroup a => GenericSemigroup (Rec a) where genericAppend' (Rec a1) (Rec a2) = Rec (genericAppend' a1 a2) -instance genericSemigroupField :: GenericSemigroup a => GenericSemigroup (Field name a) where - genericAppend' (Field a1) (Field a2) = Field (genericAppend' a1 a2) +instance genericSemigroupField :: Semigroup a => GenericSemigroup (Field name a) where + genericAppend' (Field a1) (Field a2) = Field (append a1 a2) -- | A `Generic` implementation of the `append` member from the `Semigroup` type class. genericAppend :: forall a rep. (Generic a rep, GenericSemigroup rep) => a -> a -> a @@ -177,8 +177,8 @@ instance genericMonoidArgument :: Monoid a => GenericMonoid (Argument a) where instance genericMonoidRec :: GenericMonoid a => GenericMonoid (Rec a) where genericMempty' = Rec genericMempty' -instance genericMonoidField :: GenericMonoid a => GenericMonoid (Field name a) where - genericMempty' = Field genericMempty' +instance genericMonoidField :: Monoid a => GenericMonoid (Field name a) where + genericMempty' = Field mempty -- | A `Generic` implementation of the `mempty` member from the `Monoid` type class. genericMempty :: forall a rep. (Generic a rep, GenericMonoid rep) => a From 4ef9d055f6f58dfffc5020561137b59f66f4f1bb Mon Sep 17 00:00:00 2001 From: Phil Freeman Date: Tue, 4 Oct 2016 19:32:10 -0700 Subject: [PATCH 03/33] Break modules up --- src/Data/Generic/Rep.purs | 140 ---------------------------- src/Data/Generic/Rep/Eq.purs | 41 ++++++++ src/Data/Generic/Rep/Monoid.purs | 33 +++++++ src/Data/Generic/Rep/Ord.purs | 45 +++++++++ src/Data/Generic/Rep/Semigroup.purs | 37 ++++++++ test/Main.purs | 6 +- 6 files changed, 160 insertions(+), 142 deletions(-) create mode 100644 src/Data/Generic/Rep/Eq.purs create mode 100644 src/Data/Generic/Rep/Monoid.purs create mode 100644 src/Data/Generic/Rep/Ord.purs create mode 100644 src/Data/Generic/Rep/Semigroup.purs diff --git a/src/Data/Generic/Rep.purs b/src/Data/Generic/Rep.purs index a1acc5b9..e88b966f 100644 --- a/src/Data/Generic/Rep.purs +++ b/src/Data/Generic/Rep.purs @@ -10,24 +10,8 @@ module Data.Generic.Rep , Argument(..) , Rec(..) , Field(..) - , class GenericEq - , genericEq' - , genericEq - , class GenericOrd - , genericCompare' - , genericCompare - , class GenericSemigroup - , genericAppend' - , genericAppend - , class GenericMonoid - , genericMempty' - , genericMempty ) where -import Prelude - -import Data.Monoid (class Monoid, mempty) - -- | A representation for types with no constructors. data NoConstructors @@ -59,127 +43,3 @@ newtype Field (field :: Symbol) a = Field a class Generic a rep | a -> rep where to :: rep -> a from :: a -> rep - -class GenericEq a where - genericEq' :: a -> a -> Boolean - -instance genericEqNoConstructors :: GenericEq NoConstructors where - genericEq' _ _ = true - -instance genericEqNoArguments :: GenericEq NoArguments where - genericEq' _ _ = true - -instance genericEqSum :: (GenericEq a, GenericEq b) => GenericEq (Sum a b) where - genericEq' (Inl a1) (Inl a2) = genericEq' a1 a2 - genericEq' (Inr b1) (Inr b2) = genericEq' b1 b2 - genericEq' _ _ = false - -instance genericEqProduct :: (GenericEq a, GenericEq b) => GenericEq (Product a b) where - genericEq' (Product a1 b1) (Product a2 b2) = genericEq' a1 a2 && genericEq' b1 b2 - -instance genericEqConstructor :: GenericEq a => GenericEq (Constructor name a) where - genericEq' (Constructor a1) (Constructor a2) = genericEq' a1 a2 - -instance genericEqArgument :: Eq a => GenericEq (Argument a) where - genericEq' (Argument a1) (Argument a2) = a1 == a2 - -instance genericEqRec :: GenericEq a => GenericEq (Rec a) where - genericEq' (Rec a1) (Rec a2) = genericEq' a1 a2 - -instance genericEqField :: Eq a => GenericEq (Field name a) where - genericEq' (Field a1) (Field a2) = a1 == a2 - --- | A `Generic` implementation of the `eq` member from the `Eq` type class. -genericEq :: forall a rep. (Generic a rep, GenericEq rep) => a -> a -> Boolean -genericEq x y = genericEq' (from x) (from y) - -class GenericOrd a where - genericCompare' :: a -> a -> Ordering - -instance genericOrdNoConstructors :: GenericOrd NoConstructors where - genericCompare' _ _ = EQ - -instance genericOrdNoArguments :: GenericOrd NoArguments where - genericCompare' _ _ = EQ - -instance genericOrdSum :: (GenericOrd a, GenericOrd b) => GenericOrd (Sum a b) where - genericCompare' (Inl a1) (Inl a2) = genericCompare' a1 a2 - genericCompare' (Inr b1) (Inr b2) = genericCompare' b1 b2 - genericCompare' (Inl b1) (Inr b2) = LT - genericCompare' (Inr b1) (Inl b2) = GT - -instance genericOrdProduct :: (GenericOrd a, GenericOrd b) => GenericOrd (Product a b) where - genericCompare' (Product a1 b1) (Product a2 b2) = - case genericCompare' a1 a2 of - EQ -> genericCompare' b1 b2 - other -> other - -instance genericOrdConstructor :: GenericOrd a => GenericOrd (Constructor name a) where - genericCompare' (Constructor a1) (Constructor a2) = genericCompare' a1 a2 - -instance genericOrdArgument :: Ord a => GenericOrd (Argument a) where - genericCompare' (Argument a1) (Argument a2) = compare a1 a2 - -instance genericOrdRec :: GenericOrd a => GenericOrd (Rec a) where - genericCompare' (Rec a1) (Rec a2) = genericCompare' a1 a2 - -instance genericOrdField :: Ord a => GenericOrd (Field name a) where - genericCompare' (Field a1) (Field a2) = compare a1 a2 - --- | A `Generic` implementation of the `compare` member from the `Ord` type class. -genericCompare :: forall a rep. (Generic a rep, GenericOrd rep) => a -> a -> Ordering -genericCompare x y = genericCompare' (from x) (from y) - -class GenericSemigroup a where - genericAppend' :: a -> a -> a - -instance genericSemigroupNoConstructors :: GenericSemigroup NoConstructors where - genericAppend' a _ = a - -instance genericSemigroupNoArguments :: GenericSemigroup NoArguments where - genericAppend' a _ = a - -instance genericSemigroupProduct :: (GenericSemigroup a, GenericSemigroup b) => GenericSemigroup (Product a b) where - genericAppend' (Product a1 b1) (Product a2 b2) = - Product (genericAppend' a1 a2) (genericAppend' b1 b2) - -instance genericSemigroupConstructor :: GenericSemigroup a => GenericSemigroup (Constructor name a) where - genericAppend' (Constructor a1) (Constructor a2) = Constructor (genericAppend' a1 a2) - -instance genericSemigroupArgument :: Semigroup a => GenericSemigroup (Argument a) where - genericAppend' (Argument a1) (Argument a2) = Argument (append a1 a2) - -instance genericSemigroupRec :: GenericSemigroup a => GenericSemigroup (Rec a) where - genericAppend' (Rec a1) (Rec a2) = Rec (genericAppend' a1 a2) - -instance genericSemigroupField :: Semigroup a => GenericSemigroup (Field name a) where - genericAppend' (Field a1) (Field a2) = Field (append a1 a2) - --- | A `Generic` implementation of the `append` member from the `Semigroup` type class. -genericAppend :: forall a rep. (Generic a rep, GenericSemigroup rep) => a -> a -> a -genericAppend x y = to (genericAppend' (from x) (from y)) - -class GenericMonoid a where - genericMempty' :: a - -instance genericMonoidNoArguments :: GenericMonoid NoArguments where - genericMempty' = NoArguments - -instance genericMonoidProduct :: (GenericMonoid a, GenericMonoid b) => GenericMonoid (Product a b) where - genericMempty' = Product genericMempty' genericMempty' - -instance genericMonoidConstructor :: GenericMonoid a => GenericMonoid (Constructor name a) where - genericMempty' = Constructor genericMempty' - -instance genericMonoidArgument :: Monoid a => GenericMonoid (Argument a) where - genericMempty' = Argument mempty - -instance genericMonoidRec :: GenericMonoid a => GenericMonoid (Rec a) where - genericMempty' = Rec genericMempty' - -instance genericMonoidField :: Monoid a => GenericMonoid (Field name a) where - genericMempty' = Field mempty - --- | A `Generic` implementation of the `mempty` member from the `Monoid` type class. -genericMempty :: forall a rep. (Generic a rep, GenericMonoid rep) => a -genericMempty = to genericMempty' diff --git a/src/Data/Generic/Rep/Eq.purs b/src/Data/Generic/Rep/Eq.purs new file mode 100644 index 00000000..475646bf --- /dev/null +++ b/src/Data/Generic/Rep/Eq.purs @@ -0,0 +1,41 @@ +module Data.Generic.Rep.Eq + ( class GenericEq + , genericEq' + , genericEq + ) where + +import Prelude (class Eq, (==), (&&)) +import Data.Generic.Rep + +class GenericEq a where + genericEq' :: a -> a -> Boolean + +instance genericEqNoConstructors :: GenericEq NoConstructors where + genericEq' _ _ = true + +instance genericEqNoArguments :: GenericEq NoArguments where + genericEq' _ _ = true + +instance genericEqSum :: (GenericEq a, GenericEq b) => GenericEq (Sum a b) where + genericEq' (Inl a1) (Inl a2) = genericEq' a1 a2 + genericEq' (Inr b1) (Inr b2) = genericEq' b1 b2 + genericEq' _ _ = false + +instance genericEqProduct :: (GenericEq a, GenericEq b) => GenericEq (Product a b) where + genericEq' (Product a1 b1) (Product a2 b2) = genericEq' a1 a2 && genericEq' b1 b2 + +instance genericEqConstructor :: GenericEq a => GenericEq (Constructor name a) where + genericEq' (Constructor a1) (Constructor a2) = genericEq' a1 a2 + +instance genericEqArgument :: Eq a => GenericEq (Argument a) where + genericEq' (Argument a1) (Argument a2) = a1 == a2 + +instance genericEqRec :: GenericEq a => GenericEq (Rec a) where + genericEq' (Rec a1) (Rec a2) = genericEq' a1 a2 + +instance genericEqField :: Eq a => GenericEq (Field name a) where + genericEq' (Field a1) (Field a2) = a1 == a2 + +-- | A `Generic` implementation of the `eq` member from the `Eq` type class. +genericEq :: forall a rep. (Generic a rep, GenericEq rep) => a -> a -> Boolean +genericEq x y = genericEq' (from x) (from y) diff --git a/src/Data/Generic/Rep/Monoid.purs b/src/Data/Generic/Rep/Monoid.purs new file mode 100644 index 00000000..f5436414 --- /dev/null +++ b/src/Data/Generic/Rep/Monoid.purs @@ -0,0 +1,33 @@ +module Data.Generic.Rep.Monoid + ( class GenericMonoid + , genericMempty' + , genericMempty + ) where + +import Data.Monoid (class Monoid, mempty) +import Data.Generic.Rep + +class GenericMonoid a where + genericMempty' :: a + +instance genericMonoidNoArguments :: GenericMonoid NoArguments where + genericMempty' = NoArguments + +instance genericMonoidProduct :: (GenericMonoid a, GenericMonoid b) => GenericMonoid (Product a b) where + genericMempty' = Product genericMempty' genericMempty' + +instance genericMonoidConstructor :: GenericMonoid a => GenericMonoid (Constructor name a) where + genericMempty' = Constructor genericMempty' + +instance genericMonoidArgument :: Monoid a => GenericMonoid (Argument a) where + genericMempty' = Argument mempty + +instance genericMonoidRec :: GenericMonoid a => GenericMonoid (Rec a) where + genericMempty' = Rec genericMempty' + +instance genericMonoidField :: Monoid a => GenericMonoid (Field name a) where + genericMempty' = Field mempty + +-- | A `Generic` implementation of the `mempty` member from the `Monoid` type class. +genericMempty :: forall a rep. (Generic a rep, GenericMonoid rep) => a +genericMempty = to genericMempty' diff --git a/src/Data/Generic/Rep/Ord.purs b/src/Data/Generic/Rep/Ord.purs new file mode 100644 index 00000000..e4a9c233 --- /dev/null +++ b/src/Data/Generic/Rep/Ord.purs @@ -0,0 +1,45 @@ +module Data.Generic.Rep.Ord + ( class GenericOrd + , genericCompare' + , genericCompare + ) where + +import Prelude (class Ord, compare, Ordering(..)) +import Data.Generic.Rep + +class GenericOrd a where + genericCompare' :: a -> a -> Ordering + +instance genericOrdNoConstructors :: GenericOrd NoConstructors where + genericCompare' _ _ = EQ + +instance genericOrdNoArguments :: GenericOrd NoArguments where + genericCompare' _ _ = EQ + +instance genericOrdSum :: (GenericOrd a, GenericOrd b) => GenericOrd (Sum a b) where + genericCompare' (Inl a1) (Inl a2) = genericCompare' a1 a2 + genericCompare' (Inr b1) (Inr b2) = genericCompare' b1 b2 + genericCompare' (Inl b1) (Inr b2) = LT + genericCompare' (Inr b1) (Inl b2) = GT + +instance genericOrdProduct :: (GenericOrd a, GenericOrd b) => GenericOrd (Product a b) where + genericCompare' (Product a1 b1) (Product a2 b2) = + case genericCompare' a1 a2 of + EQ -> genericCompare' b1 b2 + other -> other + +instance genericOrdConstructor :: GenericOrd a => GenericOrd (Constructor name a) where + genericCompare' (Constructor a1) (Constructor a2) = genericCompare' a1 a2 + +instance genericOrdArgument :: Ord a => GenericOrd (Argument a) where + genericCompare' (Argument a1) (Argument a2) = compare a1 a2 + +instance genericOrdRec :: GenericOrd a => GenericOrd (Rec a) where + genericCompare' (Rec a1) (Rec a2) = genericCompare' a1 a2 + +instance genericOrdField :: Ord a => GenericOrd (Field name a) where + genericCompare' (Field a1) (Field a2) = compare a1 a2 + +-- | A `Generic` implementation of the `compare` member from the `Ord` type class. +genericCompare :: forall a rep. (Generic a rep, GenericOrd rep) => a -> a -> Ordering +genericCompare x y = genericCompare' (from x) (from y) diff --git a/src/Data/Generic/Rep/Semigroup.purs b/src/Data/Generic/Rep/Semigroup.purs new file mode 100644 index 00000000..a70afab2 --- /dev/null +++ b/src/Data/Generic/Rep/Semigroup.purs @@ -0,0 +1,37 @@ +module Data.Generic.Rep.Semigroup + ( class GenericSemigroup + , genericAppend' + , genericAppend + ) where + +import Prelude (class Semigroup, append) +import Data.Generic.Rep + +class GenericSemigroup a where + genericAppend' :: a -> a -> a + +instance genericSemigroupNoConstructors :: GenericSemigroup NoConstructors where + genericAppend' a _ = a + +instance genericSemigroupNoArguments :: GenericSemigroup NoArguments where + genericAppend' a _ = a + +instance genericSemigroupProduct :: (GenericSemigroup a, GenericSemigroup b) => GenericSemigroup (Product a b) where + genericAppend' (Product a1 b1) (Product a2 b2) = + Product (genericAppend' a1 a2) (genericAppend' b1 b2) + +instance genericSemigroupConstructor :: GenericSemigroup a => GenericSemigroup (Constructor name a) where + genericAppend' (Constructor a1) (Constructor a2) = Constructor (genericAppend' a1 a2) + +instance genericSemigroupArgument :: Semigroup a => GenericSemigroup (Argument a) where + genericAppend' (Argument a1) (Argument a2) = Argument (append a1 a2) + +instance genericSemigroupRec :: GenericSemigroup a => GenericSemigroup (Rec a) where + genericAppend' (Rec a1) (Rec a2) = Rec (genericAppend' a1 a2) + +instance genericSemigroupField :: Semigroup a => GenericSemigroup (Field name a) where + genericAppend' (Field a1) (Field a2) = Field (append a1 a2) + +-- | A `Generic` implementation of the `append` member from the `Semigroup` type class. +genericAppend :: forall a rep. (Generic a rep, GenericSemigroup rep) => a -> a -> a +genericAppend x y = to (genericAppend' (from x) (from y)) diff --git a/test/Main.purs b/test/Main.purs index cccaf5f0..8f64eed5 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -4,6 +4,8 @@ import Prelude import Control.Monad.Eff (Eff) import Control.Monad.Eff.Console (CONSOLE, logShow) import Data.Generic.Rep as G +import Data.Generic.Rep.Eq as GEq +import Data.Generic.Rep.Ord as GOrd data List a = Nil | Cons a (List a) @@ -17,10 +19,10 @@ instance genericList :: G.Generic (List a) from (Cons x xs) = G.Inr (G.Constructor (G.Product (G.Argument x) (G.Argument xs))) instance eqList :: Eq a => Eq (List a) where - eq x y = G.genericEq x y + eq x y = GEq.genericEq x y instance ordList :: Ord a => Ord (List a) where - compare x y = G.genericCompare x y + compare x y = GOrd.genericCompare x y main :: Eff (console :: CONSOLE) Unit main = do From 3535d0299582566c83d64afa9f8449f5877d6f02 Mon Sep 17 00:00:00 2001 From: Phil Freeman Date: Sat, 10 Dec 2016 19:06:31 -0800 Subject: [PATCH 04/33] Deriving Show (#5) * Initial work on deriving Show * Add test for Show * Remove import * Travis etc. --- src/Data/Generic/Rep/Show.purs | 70 ++++++++++++++++++++++++++++++++++ test/Main.purs | 28 +++++++------- 2 files changed, 85 insertions(+), 13 deletions(-) create mode 100644 src/Data/Generic/Rep/Show.purs diff --git a/src/Data/Generic/Rep/Show.purs b/src/Data/Generic/Rep/Show.purs new file mode 100644 index 00000000..cab26956 --- /dev/null +++ b/src/Data/Generic/Rep/Show.purs @@ -0,0 +1,70 @@ +module Data.Generic.Rep.Show + ( class GenericShow + , genericShow' + , genericShow + , class GenericShowArgs + , genericShowArgs + , class GenericShowFields + , genericShowFields + ) where + +import Prelude (class Show, show, (<>)) +import Data.Foldable (intercalate) +import Data.Generic.Rep +import Data.Symbol (class IsSymbol, SProxy(..), reflectSymbol) + +class GenericShow a where + genericShow' :: a -> String + +class GenericShowArgs a where + genericShowArgs :: a -> Array String + +class GenericShowFields a where + genericShowFields :: a -> Array String + +instance genericShowNoConstructors :: GenericShow NoConstructors where + genericShow' a = genericShow' a + +instance genericShowArgsNoArguments :: GenericShowArgs NoArguments where + genericShowArgs _ = [] + +instance genericShowSum :: (GenericShow a, GenericShow b) => GenericShow (Sum a b) where + genericShow' (Inl a) = genericShow' a + genericShow' (Inr b) = genericShow' b + +instance genericShowArgsProduct + :: (GenericShowArgs a, GenericShowArgs b) + => GenericShowArgs (Product a b) where + genericShowArgs (Product a b) = genericShowArgs a <> genericShowArgs b + +instance genericShowFieldsProduct + :: (GenericShowFields a, GenericShowFields b) + => GenericShowFields (Product a b) where + genericShowFields (Product a b) = genericShowFields a <> genericShowFields b + +instance genericShowConstructor + :: (GenericShowArgs a, IsSymbol name) + => GenericShow (Constructor name a) where + genericShow' (Constructor a) = + case genericShowArgs a of + [] -> ctor + args -> "(" <> intercalate " " ([ctor] <> args) <> ")" + where + ctor :: String + ctor = reflectSymbol (SProxy :: SProxy name) + +instance genericShowArgsArgument :: Show a => GenericShowArgs (Argument a) where + genericShowArgs (Argument a) = [show a] + +instance genericShowArgsRec :: GenericShowFields a => GenericShowArgs (Rec a) where + genericShowArgs (Rec a) = ["{ " <> intercalate ", " (genericShowFields a) <> " }"] + +instance genericShowFieldsField + :: (Show a, IsSymbol name) + => GenericShowFields (Field name a) where + genericShowFields (Field a) = + [reflectSymbol (SProxy :: SProxy name) <> ": " <> show a] + +-- | A `Generic` implementation of the `show` member from the `Show` type class. +genericShow :: forall a rep. (Generic a rep, GenericShow rep) => a -> String +genericShow x = genericShow' (from x) diff --git a/test/Main.purs b/test/Main.purs index 8f64eed5..f8383f6a 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -6,17 +6,14 @@ import Control.Monad.Eff.Console (CONSOLE, logShow) import Data.Generic.Rep as G import Data.Generic.Rep.Eq as GEq import Data.Generic.Rep.Ord as GOrd +import Data.Generic.Rep.Show as GShow -data List a = Nil | Cons a (List a) +data List a = Nil | Cons { head :: a, tail :: List a } -instance genericList :: G.Generic (List a) - (G.Sum (G.Constructor "Nil" G.NoArguments) - (G.Constructor "Cons" (G.Product (G.Argument a) - (G.Argument (List a))))) where - to (G.Inl (G.Constructor G.NoArguments)) = Nil - to (G.Inr (G.Constructor (G.Product (G.Argument x) (G.Argument xs)))) = Cons x xs - from Nil = G.Inl (G.Constructor G.NoArguments) - from (Cons x xs) = G.Inr (G.Constructor (G.Product (G.Argument x) (G.Argument xs))) +cons :: forall a. a -> List a -> List a +cons head tail = Cons { head, tail } + +derive instance genericList :: G.Generic (List a) _ instance eqList :: Eq a => Eq (List a) where eq x y = GEq.genericEq x y @@ -24,10 +21,15 @@ instance eqList :: Eq a => Eq (List a) where instance ordList :: Ord a => Ord (List a) where compare x y = GOrd.genericCompare x y +instance showList :: Show a => Show (List a) where + show x = GShow.genericShow x + main :: Eff (console :: CONSOLE) Unit main = do - logShow (Cons 1 (Cons 2 Nil) == Cons 1 (Cons 2 Nil)) - logShow (Cons 1 (Cons 2 Nil) == Cons 1 Nil) + logShow (cons 1 (cons 2 Nil)) + + logShow (cons 1 (cons 2 Nil) == cons 1 (cons 2 Nil)) + logShow (cons 1 (cons 2 Nil) == cons 1 Nil) - logShow (Cons 1 (Cons 2 Nil) `compare` Cons 1 (Cons 2 Nil)) - logShow (Cons 1 (Cons 2 Nil) `compare` Cons 1 Nil) + logShow (cons 1 (cons 2 Nil) `compare` cons 1 (cons 2 Nil)) + logShow (cons 1 (cons 2 Nil) `compare` cons 1 Nil) From 36804af0aa85f616d2dd7ab35cfbd5d951bb7e92 Mon Sep 17 00:00:00 2001 From: Matthew Leon Date: Wed, 11 Jan 2017 17:54:55 +0000 Subject: [PATCH 05/33] Data.Generic.Rep.Bounded (#6) * Data.Generic.Rep.Bounded Generic implementations of Prelude.Bounded class's top and bottom. * GenericBounded - don't support product types * GenericBounded - only support NoArguments --- src/Data/Generic/Rep/Bounded.purs | 42 +++++++++++++++++++++++++++++++ test/Main.purs | 16 ++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 src/Data/Generic/Rep/Bounded.purs diff --git a/src/Data/Generic/Rep/Bounded.purs b/src/Data/Generic/Rep/Bounded.purs new file mode 100644 index 00000000..eedb3251 --- /dev/null +++ b/src/Data/Generic/Rep/Bounded.purs @@ -0,0 +1,42 @@ +module Data.Generic.Rep.Bounded + ( class GenericBottom + , genericBottom' + , genericBottom + , class GenericTop + , genericTop' + , genericTop + ) where + +import Data.Generic.Rep + +class GenericBottom a where + genericBottom' :: a + +instance genericBottomNoArguments :: GenericBottom NoArguments where + genericBottom' = NoArguments + +instance genericBottomSum :: GenericBottom a => GenericBottom (Sum a b) where + genericBottom' = Inl genericBottom' + +instance genericBottomConstructor :: GenericBottom a => GenericBottom (Constructor name a) where + genericBottom' = Constructor genericBottom' + +class GenericTop a where + genericTop' :: a + +instance genericTopNoArguments :: GenericTop NoArguments where + genericTop' = NoArguments + +instance genericTopSum :: GenericTop b => GenericTop (Sum a b) where + genericTop' = Inr genericTop' + +instance genericTopConstructor :: GenericTop a => GenericTop (Constructor name a) where + genericTop' = Constructor genericTop' + +-- | A `Generic` implementation of the `bottom` member from the `Bounded` type class. +genericBottom :: forall a rep. (Generic a rep, GenericBottom rep) => a +genericBottom = to genericBottom' + +-- | A `Generic` implementation of the `top` member from the `Bounded` type class. +genericTop :: forall a rep. (Generic a rep, GenericTop rep) => a +genericTop = to genericTop' diff --git a/test/Main.purs b/test/Main.purs index f8383f6a..d661c9b9 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -7,6 +7,7 @@ import Data.Generic.Rep as G import Data.Generic.Rep.Eq as GEq import Data.Generic.Rep.Ord as GOrd import Data.Generic.Rep.Show as GShow +import Data.Generic.Rep.Bounded as GBounded data List a = Nil | Cons { head :: a, tail :: List a } @@ -24,6 +25,18 @@ instance ordList :: Ord a => Ord (List a) where instance showList :: Show a => Show (List a) where show x = GShow.genericShow x +data SimpleBounded = A | B | C | D +derive instance genericSimpleBounded :: G.Generic SimpleBounded _ +instance eqSimpleBounded :: Eq SimpleBounded where + eq x y = GEq.genericEq x y +instance ordSimpleBounded :: Ord SimpleBounded where + compare x y = GOrd.genericCompare x y +instance showSimpleBounded :: Show SimpleBounded where + show x = GShow.genericShow x +instance boundedSimpleBounded :: Bounded SimpleBounded where + bottom = GBounded.genericBottom + top = GBounded.genericTop + main :: Eff (console :: CONSOLE) Unit main = do logShow (cons 1 (cons 2 Nil)) @@ -33,3 +46,6 @@ main = do logShow (cons 1 (cons 2 Nil) `compare` cons 1 (cons 2 Nil)) logShow (cons 1 (cons 2 Nil) `compare` cons 1 Nil) + + logShow (bottom :: SimpleBounded) + logShow (top :: SimpleBounded) From 1d325b3fad4deeaa471332062dae444ef4bb290d Mon Sep 17 00:00:00 2001 From: Gary Burgess Date: Sun, 12 Mar 2017 15:02:41 +0000 Subject: [PATCH 06/33] Update for PureScript 0.11 --- src/Data/Generic/Rep/Bounded.purs | 4 ++-- src/Data/Generic/Rep/Eq.purs | 2 +- src/Data/Generic/Rep/Monoid.purs | 2 +- src/Data/Generic/Rep/Ord.purs | 2 +- src/Data/Generic/Rep/Semigroup.purs | 2 +- src/Data/Generic/Rep/Show.purs | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Data/Generic/Rep/Bounded.purs b/src/Data/Generic/Rep/Bounded.purs index eedb3251..b2eb7897 100644 --- a/src/Data/Generic/Rep/Bounded.purs +++ b/src/Data/Generic/Rep/Bounded.purs @@ -34,9 +34,9 @@ instance genericTopConstructor :: GenericTop a => GenericTop (Constructor name a genericTop' = Constructor genericTop' -- | A `Generic` implementation of the `bottom` member from the `Bounded` type class. -genericBottom :: forall a rep. (Generic a rep, GenericBottom rep) => a +genericBottom :: forall a rep. Generic a rep => GenericBottom rep => a genericBottom = to genericBottom' -- | A `Generic` implementation of the `top` member from the `Bounded` type class. -genericTop :: forall a rep. (Generic a rep, GenericTop rep) => a +genericTop :: forall a rep. Generic a rep => GenericTop rep => a genericTop = to genericTop' diff --git a/src/Data/Generic/Rep/Eq.purs b/src/Data/Generic/Rep/Eq.purs index 475646bf..09a9ff54 100644 --- a/src/Data/Generic/Rep/Eq.purs +++ b/src/Data/Generic/Rep/Eq.purs @@ -37,5 +37,5 @@ instance genericEqField :: Eq a => GenericEq (Field name a) where genericEq' (Field a1) (Field a2) = a1 == a2 -- | A `Generic` implementation of the `eq` member from the `Eq` type class. -genericEq :: forall a rep. (Generic a rep, GenericEq rep) => a -> a -> Boolean +genericEq :: forall a rep. Generic a rep => GenericEq rep => a -> a -> Boolean genericEq x y = genericEq' (from x) (from y) diff --git a/src/Data/Generic/Rep/Monoid.purs b/src/Data/Generic/Rep/Monoid.purs index f5436414..d2ceddf0 100644 --- a/src/Data/Generic/Rep/Monoid.purs +++ b/src/Data/Generic/Rep/Monoid.purs @@ -29,5 +29,5 @@ instance genericMonoidField :: Monoid a => GenericMonoid (Field name a) where genericMempty' = Field mempty -- | A `Generic` implementation of the `mempty` member from the `Monoid` type class. -genericMempty :: forall a rep. (Generic a rep, GenericMonoid rep) => a +genericMempty :: forall a rep. Generic a rep => GenericMonoid rep => a genericMempty = to genericMempty' diff --git a/src/Data/Generic/Rep/Ord.purs b/src/Data/Generic/Rep/Ord.purs index e4a9c233..0136f21f 100644 --- a/src/Data/Generic/Rep/Ord.purs +++ b/src/Data/Generic/Rep/Ord.purs @@ -41,5 +41,5 @@ instance genericOrdField :: Ord a => GenericOrd (Field name a) where genericCompare' (Field a1) (Field a2) = compare a1 a2 -- | A `Generic` implementation of the `compare` member from the `Ord` type class. -genericCompare :: forall a rep. (Generic a rep, GenericOrd rep) => a -> a -> Ordering +genericCompare :: forall a rep. Generic a rep => GenericOrd rep => a -> a -> Ordering genericCompare x y = genericCompare' (from x) (from y) diff --git a/src/Data/Generic/Rep/Semigroup.purs b/src/Data/Generic/Rep/Semigroup.purs index a70afab2..e36e5721 100644 --- a/src/Data/Generic/Rep/Semigroup.purs +++ b/src/Data/Generic/Rep/Semigroup.purs @@ -33,5 +33,5 @@ instance genericSemigroupField :: Semigroup a => GenericSemigroup (Field name a) genericAppend' (Field a1) (Field a2) = Field (append a1 a2) -- | A `Generic` implementation of the `append` member from the `Semigroup` type class. -genericAppend :: forall a rep. (Generic a rep, GenericSemigroup rep) => a -> a -> a +genericAppend :: forall a rep. Generic a rep => GenericSemigroup rep => a -> a -> a genericAppend x y = to (genericAppend' (from x) (from y)) diff --git a/src/Data/Generic/Rep/Show.purs b/src/Data/Generic/Rep/Show.purs index cab26956..edd233dc 100644 --- a/src/Data/Generic/Rep/Show.purs +++ b/src/Data/Generic/Rep/Show.purs @@ -66,5 +66,5 @@ instance genericShowFieldsField [reflectSymbol (SProxy :: SProxy name) <> ": " <> show a] -- | A `Generic` implementation of the `show` member from the `Show` type class. -genericShow :: forall a rep. (Generic a rep, GenericShow rep) => a -> String +genericShow :: forall a rep. Generic a rep => GenericShow rep => a -> String genericShow x = genericShow' (from x) From 0cbb8dfe2946ba3f31a055842028985f9c4339ee Mon Sep 17 00:00:00 2001 From: Liam Goodacre Date: Sat, 3 Jun 2017 22:04:33 +0100 Subject: [PATCH 07/33] Add Generic instance for Maybe (#9) --- src/Data/Generic/Rep.purs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Data/Generic/Rep.purs b/src/Data/Generic/Rep.purs index e88b966f..9f1c47f9 100644 --- a/src/Data/Generic/Rep.purs +++ b/src/Data/Generic/Rep.purs @@ -12,6 +12,8 @@ module Data.Generic.Rep , Field(..) ) where +import Data.Maybe (Maybe(..)) + -- | A representation for types with no constructors. data NoConstructors @@ -43,3 +45,13 @@ newtype Field (field :: Symbol) a = Field a class Generic a rep | a -> rep where to :: rep -> a from :: a -> rep + +instance genericMaybe + :: Generic (Maybe a) (Sum (Constructor "Nothing" NoArguments) + (Constructor "Just" (Argument a))) where + to (Inl _) = Nothing + to (Inr (Constructor (Argument a))) = Just a + + from Nothing = Inl (Constructor NoArguments) + from (Just a) = Inr (Constructor (Argument a)) + From 75f6da8b6a807b2cf77ea4b844b9b98a9e99415d Mon Sep 17 00:00:00 2001 From: Gary Burgess Date: Sat, 5 Aug 2017 15:53:52 +0100 Subject: [PATCH 08/33] Add missing Bounded instances for Argument --- src/Data/Generic/Rep/Bounded.purs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Data/Generic/Rep/Bounded.purs b/src/Data/Generic/Rep/Bounded.purs index b2eb7897..9ba33e3e 100644 --- a/src/Data/Generic/Rep/Bounded.purs +++ b/src/Data/Generic/Rep/Bounded.purs @@ -9,12 +9,17 @@ module Data.Generic.Rep.Bounded import Data.Generic.Rep +import Data.Bounded (class Bounded, bottom, top) + class GenericBottom a where genericBottom' :: a instance genericBottomNoArguments :: GenericBottom NoArguments where genericBottom' = NoArguments +instance genericBottomArgument :: Bounded a => GenericBottom (Argument a) where + genericBottom' = Argument bottom + instance genericBottomSum :: GenericBottom a => GenericBottom (Sum a b) where genericBottom' = Inl genericBottom' @@ -27,6 +32,9 @@ class GenericTop a where instance genericTopNoArguments :: GenericTop NoArguments where genericTop' = NoArguments +instance genericTopArgument :: Bounded a => GenericTop (Argument a) where + genericTop' = Argument top + instance genericTopSum :: GenericTop b => GenericTop (Sum a b) where genericTop' = Inr genericTop' From 793d1d470ed034bf489491ae33f72a7a2b9305e7 Mon Sep 17 00:00:00 2001 From: Gary Burgess Date: Sat, 5 Aug 2017 15:54:15 +0100 Subject: [PATCH 09/33] Add GenericEnum and GenericBoundedEnum --- src/Data/Generic/Rep/Enum.purs | 95 ++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 src/Data/Generic/Rep/Enum.purs diff --git a/src/Data/Generic/Rep/Enum.purs b/src/Data/Generic/Rep/Enum.purs new file mode 100644 index 00000000..767cacd9 --- /dev/null +++ b/src/Data/Generic/Rep/Enum.purs @@ -0,0 +1,95 @@ +module Data.Generic.Rep.Enum where + +import Prelude + +import Data.Enum (class BoundedEnum, class Enum, Cardinality(..), cardinality, fromEnum, pred, succ, toEnum) +import Data.Generic.Rep (class Generic, Argument(..), Constructor(..), NoArguments(..), Sum(..), from, to) +import Data.Generic.Rep.Bounded (class GenericBottom, class GenericTop, genericBottom', genericTop') +import Data.Maybe (Maybe(..)) +import Data.Newtype (unwrap) + +class GenericEnum a where + genericPred' :: a -> Maybe a + genericSucc' :: a -> Maybe a + +instance genericEnumNoArguments :: GenericEnum NoArguments where + genericPred' _ = Nothing + genericSucc' _ = Nothing + +instance genericEnumArgument :: Enum a => GenericEnum (Argument a) where + genericPred' (Argument a) = Argument <$> pred a + genericSucc' (Argument a) = Argument <$> succ a + +instance genericEnumConstructor :: GenericEnum a => GenericEnum (Constructor name a) where + genericPred' (Constructor a) = Constructor <$> genericPred' a + genericSucc' (Constructor a) = Constructor <$> genericSucc' a + +instance genericEnumSum :: (GenericEnum a, GenericTop a, GenericEnum b, GenericBottom b) => GenericEnum (Sum a b) where + genericPred' = case _ of + Inl a -> Inl <$> genericPred' a + Inr b -> case genericPred' b of + Nothing -> Just (Inl genericTop') + Just b' -> Just (Inr b') + genericSucc' = case _ of + Inl a -> case genericSucc' a of + Nothing -> Just (Inr genericBottom') + Just a' -> Just (Inl a') + Inr b -> Inr <$> genericSucc' b + +-- | A `Generic` implementation of the `pred` member from the `Enum` type class. +genericPred :: forall a rep. Generic a rep => GenericEnum rep => a -> Maybe a +genericPred = map to <<< genericPred' <<< from + +-- | A `Generic` implementation of the `succ` member from the `Enum` type class. +genericSucc :: forall a rep. Generic a rep => GenericEnum rep => a -> Maybe a +genericSucc = map to <<< genericSucc' <<< from + +class GenericBoundedEnum a where + genericCardinality' :: Cardinality a + genericToEnum' :: Int -> Maybe a + genericFromEnum' :: a -> Int + +instance genericBoundedEnumNoArguments :: GenericBoundedEnum NoArguments where + genericCardinality' = Cardinality 1 + genericToEnum' i = if i == 0 then Just NoArguments else Nothing + genericFromEnum' _ = 0 + +instance genericBoundedEnumArgument :: BoundedEnum a => GenericBoundedEnum (Argument a) where + genericCardinality' = Cardinality (unwrap (cardinality :: Cardinality a)) + genericToEnum' i = Argument <$> toEnum i + genericFromEnum' (Argument a) = fromEnum a + +instance genericBoundedEnumConstructor :: GenericBoundedEnum a => GenericBoundedEnum (Constructor name a) where + genericCardinality' = Cardinality (unwrap (genericCardinality' :: Cardinality a)) + genericToEnum' i = Constructor <$> genericToEnum' i + genericFromEnum' (Constructor a) = genericFromEnum' a + +instance genericBoundedEnumSum :: (GenericBoundedEnum a, GenericBoundedEnum b) => GenericBoundedEnum (Sum a b) where + genericCardinality' = + Cardinality + $ unwrap (genericCardinality' :: Cardinality a) + + unwrap (genericCardinality' :: Cardinality b) + genericToEnum' n = to genericCardinality' + where + to :: Cardinality a -> Maybe (Sum a b) + to (Cardinality ca) + | n >= 0 && n < ca = Inl <$> genericToEnum' n + | otherwise = Inr <$> genericToEnum' (n - ca) + genericFromEnum' = case _ of + Inl a -> genericFromEnum' a + Inr b -> genericFromEnum' b + unwrap (genericCardinality' :: Cardinality a) + +-- | A `Generic` implementation of the `cardinality` member from the +-- | `BoundedEnum` type class. +genericCardinality :: forall a rep. Generic a rep => GenericBoundedEnum rep => Cardinality a +genericCardinality = Cardinality (unwrap (genericCardinality' :: Cardinality rep)) + +-- | A `Generic` implementation of the `toEnum` member from the `BoundedEnum` +-- | type class. +genericToEnum :: forall a rep. Generic a rep => GenericBoundedEnum rep => Int -> Maybe a +genericToEnum = map to <<< genericToEnum' + +-- | A `Generic` implementation of the `fromEnum` member from the `BoundedEnum` +-- | type class. +genericFromEnum :: forall a rep. Generic a rep => GenericBoundedEnum rep => a -> Int +genericFromEnum = genericFromEnum' <<< from From 530077098b5bf0789992ed5817f9b661a2495d24 Mon Sep 17 00:00:00 2001 From: Gary Burgess Date: Sat, 5 Aug 2017 16:14:34 +0100 Subject: [PATCH 10/33] Add enum tests, convert existing "tests" into assertions --- test/Main.purs | 105 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 96 insertions(+), 9 deletions(-) diff --git a/test/Main.purs b/test/Main.purs index d661c9b9..662bf814 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -1,13 +1,18 @@ module Test.Main where import Prelude + import Control.Monad.Eff (Eff) -import Control.Monad.Eff.Console (CONSOLE, logShow) +import Control.Monad.Eff.Console (CONSOLE, log, logShow) +import Data.Enum (class BoundedEnum, class Enum, Cardinality(..), cardinality, fromEnum, pred, succ, toEnum) import Data.Generic.Rep as G +import Data.Generic.Rep.Bounded as GBounded +import Data.Generic.Rep.Enum as GEnum import Data.Generic.Rep.Eq as GEq import Data.Generic.Rep.Ord as GOrd import Data.Generic.Rep.Show as GShow -import Data.Generic.Rep.Bounded as GBounded +import Data.Maybe (Maybe(..)) +import Test.Assert (ASSERT, assert) data List a = Nil | Cons { head :: a, tail :: List a } @@ -36,16 +41,98 @@ instance showSimpleBounded :: Show SimpleBounded where instance boundedSimpleBounded :: Bounded SimpleBounded where bottom = GBounded.genericBottom top = GBounded.genericTop +instance enumSimpleBounded :: Enum SimpleBounded where + pred = GEnum.genericPred + succ = GEnum.genericSucc +instance boundedEnumSimpleBounded :: BoundedEnum SimpleBounded where + cardinality = GEnum.genericCardinality + toEnum = GEnum.genericToEnum + fromEnum = GEnum.genericFromEnum + +data Option a = None | Some a +derive instance genericOption :: G.Generic (Option a) _ +instance eqOption :: Eq a => Eq (Option a) where + eq x y = GEq.genericEq x y +instance ordOption :: Ord a => Ord (Option a) where + compare x y = GOrd.genericCompare x y +instance showOption :: Show a => Show (Option a) where + show x = GShow.genericShow x +instance boundedOption :: Bounded a => Bounded (Option a) where + bottom = GBounded.genericBottom + top = GBounded.genericTop +instance enumOption :: (Bounded a, Enum a) => Enum (Option a) where + pred = GEnum.genericPred + succ = GEnum.genericSucc +instance boundedEnumOption :: BoundedEnum a => BoundedEnum (Option a) where + cardinality = GEnum.genericCardinality + toEnum = GEnum.genericToEnum + fromEnum = GEnum.genericFromEnum -main :: Eff (console :: CONSOLE) Unit +main :: Eff (console :: CONSOLE, assert :: ASSERT) Unit main = do logShow (cons 1 (cons 2 Nil)) - logShow (cons 1 (cons 2 Nil) == cons 1 (cons 2 Nil)) - logShow (cons 1 (cons 2 Nil) == cons 1 Nil) + log "Checking equality" + assert $ cons 1 (cons 2 Nil) == cons 1 (cons 2 Nil) + + log "Checking inequality" + assert $ cons 1 (cons 2 Nil) /= cons 1 Nil + + log "Checking comparison EQ" + assert $ (cons 1 (cons 2 Nil) `compare` cons 1 (cons 2 Nil)) == EQ + + log "Checking comparison GT" + assert $ (cons 1 (cons 2 Nil) `compare` cons 1 Nil) == GT + + log "Checking comparison LT" + assert $ (cons 1 Nil `compare` cons 1 (cons 2 Nil)) == LT + + log "Checking simple bottom" + assert $ bottom == A + + log "Checking simple top" + assert $ top == D + + log "Checking composite bottom" + assert $ bottom == None :: Option SimpleBounded + + log "Checking composite top" + assert $ top == Some D + + log "Checking simple pred bottom" + assert $ pred (bottom :: SimpleBounded) == Nothing + + log "Checking simple (pred =<< succ bottom)" + assert $ (pred =<< succ bottom) == Just A + + log "Checking simple succ top" + assert $ succ (top :: SimpleBounded) == Nothing + + log "Checking simple (succ =<< pred top)" + assert $ (succ =<< pred top) == Just D + + log "Checking composite pred bottom" + assert $ pred (bottom :: Option SimpleBounded) == Nothing + + log "Checking composite (pred =<< succ bottom)" + assert $ (pred =<< succ (bottom :: Option SimpleBounded)) == Just None + + log "Checking composite succ top" + assert $ succ (top :: Option SimpleBounded) == Nothing + + log "Checking composite (succ =<< pred top)" + assert $ (succ =<< pred top) == Just (Some D) + + log "Checking simple cardinality" + assert $ (cardinality :: Cardinality SimpleBounded) == Cardinality 4 + + log "Checking composite cardinality" + assert $ (cardinality :: Cardinality (Option SimpleBounded)) == Cardinality 5 - logShow (cons 1 (cons 2 Nil) `compare` cons 1 (cons 2 Nil)) - logShow (cons 1 (cons 2 Nil) `compare` cons 1 Nil) + log "Checking simple toEnum/fromEnum roundtrip" + assert $ toEnum (fromEnum A) == Just A + assert $ toEnum (fromEnum B) == Just B - logShow (bottom :: SimpleBounded) - logShow (top :: SimpleBounded) + log "Checking composite toEnum/fromEnum roundtrip" + assert $ toEnum (fromEnum (None :: Option SimpleBounded)) == Just (None :: Option SimpleBounded) + assert $ toEnum (fromEnum (Some A)) == Just (Some A) From b31a5ec81a87a6f215ec1e54e236e81e7e8ea007 Mon Sep 17 00:00:00 2001 From: Jorge Acereda Date: Thu, 31 Aug 2017 18:30:03 +0200 Subject: [PATCH 11/33] Product instances in Bounded and Enum --- src/Data/Generic/Rep/Bounded.purs | 6 +++ src/Data/Generic/Rep/Enum.purs | 25 +++++++++++- test/Main.purs | 66 ++++++++++++++++++++++++++++++- 3 files changed, 95 insertions(+), 2 deletions(-) diff --git a/src/Data/Generic/Rep/Bounded.purs b/src/Data/Generic/Rep/Bounded.purs index 9ba33e3e..8b1ec859 100644 --- a/src/Data/Generic/Rep/Bounded.purs +++ b/src/Data/Generic/Rep/Bounded.purs @@ -23,6 +23,9 @@ instance genericBottomArgument :: Bounded a => GenericBottom (Argument a) where instance genericBottomSum :: GenericBottom a => GenericBottom (Sum a b) where genericBottom' = Inl genericBottom' +instance genericBottomProduct :: (GenericBottom a, GenericBottom b) => GenericBottom (Product a b) where + genericBottom' = Product genericBottom' genericBottom' + instance genericBottomConstructor :: GenericBottom a => GenericBottom (Constructor name a) where genericBottom' = Constructor genericBottom' @@ -38,6 +41,9 @@ instance genericTopArgument :: Bounded a => GenericTop (Argument a) where instance genericTopSum :: GenericTop b => GenericTop (Sum a b) where genericTop' = Inr genericTop' +instance genericTopProduct :: (GenericTop a, GenericTop b) => GenericTop (Product a b) where + genericTop' = Product genericTop' genericTop' + instance genericTopConstructor :: GenericTop a => GenericTop (Constructor name a) where genericTop' = Constructor genericTop' diff --git a/src/Data/Generic/Rep/Enum.purs b/src/Data/Generic/Rep/Enum.purs index 767cacd9..594729cf 100644 --- a/src/Data/Generic/Rep/Enum.purs +++ b/src/Data/Generic/Rep/Enum.purs @@ -3,7 +3,7 @@ module Data.Generic.Rep.Enum where import Prelude import Data.Enum (class BoundedEnum, class Enum, Cardinality(..), cardinality, fromEnum, pred, succ, toEnum) -import Data.Generic.Rep (class Generic, Argument(..), Constructor(..), NoArguments(..), Sum(..), from, to) +import Data.Generic.Rep (class Generic, Argument(..), Constructor(..), NoArguments(..), Product(..), Sum(..), from, to) import Data.Generic.Rep.Bounded (class GenericBottom, class GenericTop, genericBottom', genericTop') import Data.Maybe (Maybe(..)) import Data.Newtype (unwrap) @@ -36,6 +36,15 @@ instance genericEnumSum :: (GenericEnum a, GenericTop a, GenericEnum b, GenericB Just a' -> Just (Inl a') Inr b -> Inr <$> genericSucc' b +instance genericEnumProduct :: (GenericEnum a, GenericTop a, GenericBottom a, GenericEnum b, GenericTop b, GenericBottom b) => GenericEnum (Product a b) where + genericPred' (Product a b) = case genericPred' b of + Just p -> Just $ Product a p + Nothing -> flip Product genericTop' <$> genericPred' a + genericSucc' (Product a b) = case genericSucc' b of + Just s -> Just $ Product a s + Nothing -> flip Product genericBottom' <$> genericSucc' a + + -- | A `Generic` implementation of the `pred` member from the `Enum` type class. genericPred :: forall a rep. Generic a rep => GenericEnum rep => a -> Maybe a genericPred = map to <<< genericPred' <<< from @@ -79,6 +88,20 @@ instance genericBoundedEnumSum :: (GenericBoundedEnum a, GenericBoundedEnum b) = Inl a -> genericFromEnum' a Inr b -> genericFromEnum' b + unwrap (genericCardinality' :: Cardinality a) + +instance genericBoundedEnumProduct :: (GenericBoundedEnum a, GenericBoundedEnum b) => GenericBoundedEnum (Product a b) where + genericCardinality' = + Cardinality + $ unwrap (genericCardinality' :: Cardinality a) + * unwrap (genericCardinality' :: Cardinality b) + genericToEnum' n = to genericCardinality' + where to :: Cardinality b -> Maybe (Product a b) + to (Cardinality cb) = Product <$> (genericToEnum' $ n `div` cb) <*> (genericToEnum' $ n `mod` cb) + genericFromEnum' = from genericCardinality' + where from :: Cardinality b -> (Product a b) -> Int + from (Cardinality cb) (Product a b) = genericFromEnum' a * cb + genericFromEnum' b + + -- | A `Generic` implementation of the `cardinality` member from the -- | `BoundedEnum` type class. genericCardinality :: forall a rep. Generic a rep => GenericBoundedEnum rep => Cardinality a diff --git a/test/Main.purs b/test/Main.purs index 662bf814..2dc987bf 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -4,7 +4,7 @@ import Prelude import Control.Monad.Eff (Eff) import Control.Monad.Eff.Console (CONSOLE, log, logShow) -import Data.Enum (class BoundedEnum, class Enum, Cardinality(..), cardinality, fromEnum, pred, succ, toEnum) +import Data.Enum (class BoundedEnum, class Enum, Cardinality(..), cardinality, fromEnum, pred, succ, toEnum, enumFromTo) import Data.Generic.Rep as G import Data.Generic.Rep.Bounded as GBounded import Data.Generic.Rep.Enum as GEnum @@ -68,6 +68,45 @@ instance boundedEnumOption :: BoundedEnum a => BoundedEnum (Option a) where toEnum = GEnum.genericToEnum fromEnum = GEnum.genericFromEnum +data Bit = Zero | One +derive instance genericBit :: G.Generic Bit _ +instance eqBit :: Eq Bit where + eq x y = GEq.genericEq x y +instance ordBit :: Ord Bit where + compare x y = GOrd.genericCompare x y +instance showBit :: Show Bit where + show x = GShow.genericShow x +instance boundedBit :: Bounded Bit where + bottom = GBounded.genericBottom + top = GBounded.genericTop +instance enumBit :: Enum Bit where + pred = GEnum.genericPred + succ = GEnum.genericSucc +instance boundedEnumBit :: BoundedEnum Bit where + cardinality = GEnum.genericCardinality + toEnum = GEnum.genericToEnum + fromEnum = GEnum.genericFromEnum + +data Pair a b = Pair a b +derive instance genericPair :: G.Generic (Pair a b) _ +instance eqPair :: (Eq a, Eq b) => Eq (Pair a b) where + eq = GEq.genericEq +instance ordPair :: (Ord a, Ord b) => Ord (Pair a b) where + compare = GOrd.genericCompare +instance showPair :: (Show a, Show b) => Show (Pair a b) where + show = GShow.genericShow +instance boundedPair :: (Bounded a, Bounded b) => Bounded (Pair a b) where + bottom = GBounded.genericBottom + top = GBounded.genericTop +instance enumPair :: (Bounded a, Enum a, Bounded b, Enum b) => Enum (Pair a b) where + pred = GEnum.genericPred + succ = GEnum.genericSucc +instance boundedEnumPair :: (BoundedEnum a, BoundedEnum b) => BoundedEnum (Pair a b) where + cardinality = GEnum.genericCardinality + toEnum = GEnum.genericToEnum + fromEnum = GEnum.genericFromEnum + + main :: Eff (console :: CONSOLE, assert :: ASSERT) Unit main = do logShow (cons 1 (cons 2 Nil)) @@ -99,6 +138,12 @@ main = do log "Checking composite top" assert $ top == Some D + log "Checking product bottom" + assert $ bottom == Pair Zero A :: Pair Bit SimpleBounded + + log "Checking product top" + assert $ top == Pair One D :: Pair Bit SimpleBounded + log "Checking simple pred bottom" assert $ pred (bottom :: SimpleBounded) == Nothing @@ -123,12 +168,27 @@ main = do log "Checking composite (succ =<< pred top)" assert $ (succ =<< pred top) == Just (Some D) + log "Checking product pred bottom" + assert $ pred (bottom :: Pair Bit SimpleBounded) == Nothing + + log "Checking product (pred =<< succ bottom)" + assert $ (pred =<< succ (bottom :: Pair Bit SimpleBounded)) == Just (Pair Zero A) + + log "Checking product succ top" + assert $ succ (top :: Pair Bit SimpleBounded) == Nothing + + log "Checking product (succ =<< pred top)" + assert $ (succ =<< pred top) == Just (Pair One D) + log "Checking simple cardinality" assert $ (cardinality :: Cardinality SimpleBounded) == Cardinality 4 log "Checking composite cardinality" assert $ (cardinality :: Cardinality (Option SimpleBounded)) == Cardinality 5 + log "Checking product cardinality" + assert $ (cardinality :: Cardinality (Pair Bit SimpleBounded)) == Cardinality 8 + log "Checking simple toEnum/fromEnum roundtrip" assert $ toEnum (fromEnum A) == Just A assert $ toEnum (fromEnum B) == Just B @@ -136,3 +196,7 @@ main = do log "Checking composite toEnum/fromEnum roundtrip" assert $ toEnum (fromEnum (None :: Option SimpleBounded)) == Just (None :: Option SimpleBounded) assert $ toEnum (fromEnum (Some A)) == Just (Some A) + + log "Checking product toEnum/fromEnum roundtrip" + assert $ let allPairs = enumFromTo bottom top :: Array (Pair Bit SimpleBounded) + in toEnum <<< fromEnum <$> allPairs == Just <$> allPairs From 5fc435bb4bc6d047981ad60f322c69fe01d53c44 Mon Sep 17 00:00:00 2001 From: Kristoffer Josefsson Date: Mon, 4 Dec 2017 13:04:04 -0500 Subject: [PATCH 12/33] Added GenericShowFields instances for NoConstructors and NoArguments (#20) * Added Eq and Show instances to NoArguments and NoConstructors * Added GenericShowFields * Removed Show, Eq * Cleanup * Removed NoConstructors Show instance --- src/Data/Generic/Rep/Show.purs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Data/Generic/Rep/Show.purs b/src/Data/Generic/Rep/Show.purs index edd233dc..9b64ff08 100644 --- a/src/Data/Generic/Rep/Show.purs +++ b/src/Data/Generic/Rep/Show.purs @@ -65,6 +65,9 @@ instance genericShowFieldsField genericShowFields (Field a) = [reflectSymbol (SProxy :: SProxy name) <> ": " <> show a] +instance genericShowFieldsNoArguments :: GenericShowFields NoArguments where + genericShowFields _ = [] + -- | A `Generic` implementation of the `show` member from the `Show` type class. genericShow :: forall a rep. Generic a rep => GenericShow rep => a -> String genericShow x = genericShow' (from x) From 9bbb4463724d75905475ab112b5ee1ab3ae737eb Mon Sep 17 00:00:00 2001 From: Liam Goodacre Date: Wed, 11 Apr 2018 22:41:34 +0100 Subject: [PATCH 13/33] Remove Rec and Field & update package & bower symbols --- src/Data/Generic/Rep.purs | 9 --------- src/Data/Generic/Rep/Eq.purs | 6 ------ src/Data/Generic/Rep/Monoid.purs | 6 ------ src/Data/Generic/Rep/Ord.purs | 6 ------ src/Data/Generic/Rep/Semigroup.purs | 6 ------ src/Data/Generic/Rep/Show.purs | 22 ---------------------- 6 files changed, 55 deletions(-) diff --git a/src/Data/Generic/Rep.purs b/src/Data/Generic/Rep.purs index 9f1c47f9..92bf8459 100644 --- a/src/Data/Generic/Rep.purs +++ b/src/Data/Generic/Rep.purs @@ -8,8 +8,6 @@ module Data.Generic.Rep , Product(..) , Constructor(..) , Argument(..) - , Rec(..) - , Field(..) ) where import Data.Maybe (Maybe(..)) @@ -33,13 +31,6 @@ newtype Constructor (name :: Symbol) a = Constructor a -- | A representation for an argument in a data constructor. newtype Argument a = Argument a --- | A representation for records. -newtype Rec fields = Rec fields - --- | A representation for a record field which includes the field name --- | as a type-level string. -newtype Field (field :: Symbol) a = Field a - -- | The `Generic` class asserts the existence of a type function from types -- | to their representations using the type constructors defined in this module. class Generic a rep | a -> rep where diff --git a/src/Data/Generic/Rep/Eq.purs b/src/Data/Generic/Rep/Eq.purs index 09a9ff54..fe09ab0f 100644 --- a/src/Data/Generic/Rep/Eq.purs +++ b/src/Data/Generic/Rep/Eq.purs @@ -30,12 +30,6 @@ instance genericEqConstructor :: GenericEq a => GenericEq (Constructor name a) w instance genericEqArgument :: Eq a => GenericEq (Argument a) where genericEq' (Argument a1) (Argument a2) = a1 == a2 -instance genericEqRec :: GenericEq a => GenericEq (Rec a) where - genericEq' (Rec a1) (Rec a2) = genericEq' a1 a2 - -instance genericEqField :: Eq a => GenericEq (Field name a) where - genericEq' (Field a1) (Field a2) = a1 == a2 - -- | A `Generic` implementation of the `eq` member from the `Eq` type class. genericEq :: forall a rep. Generic a rep => GenericEq rep => a -> a -> Boolean genericEq x y = genericEq' (from x) (from y) diff --git a/src/Data/Generic/Rep/Monoid.purs b/src/Data/Generic/Rep/Monoid.purs index d2ceddf0..999b2f59 100644 --- a/src/Data/Generic/Rep/Monoid.purs +++ b/src/Data/Generic/Rep/Monoid.purs @@ -22,12 +22,6 @@ instance genericMonoidConstructor :: GenericMonoid a => GenericMonoid (Construct instance genericMonoidArgument :: Monoid a => GenericMonoid (Argument a) where genericMempty' = Argument mempty -instance genericMonoidRec :: GenericMonoid a => GenericMonoid (Rec a) where - genericMempty' = Rec genericMempty' - -instance genericMonoidField :: Monoid a => GenericMonoid (Field name a) where - genericMempty' = Field mempty - -- | A `Generic` implementation of the `mempty` member from the `Monoid` type class. genericMempty :: forall a rep. Generic a rep => GenericMonoid rep => a genericMempty = to genericMempty' diff --git a/src/Data/Generic/Rep/Ord.purs b/src/Data/Generic/Rep/Ord.purs index 0136f21f..ad7c45c7 100644 --- a/src/Data/Generic/Rep/Ord.purs +++ b/src/Data/Generic/Rep/Ord.purs @@ -34,12 +34,6 @@ instance genericOrdConstructor :: GenericOrd a => GenericOrd (Constructor name a instance genericOrdArgument :: Ord a => GenericOrd (Argument a) where genericCompare' (Argument a1) (Argument a2) = compare a1 a2 -instance genericOrdRec :: GenericOrd a => GenericOrd (Rec a) where - genericCompare' (Rec a1) (Rec a2) = genericCompare' a1 a2 - -instance genericOrdField :: Ord a => GenericOrd (Field name a) where - genericCompare' (Field a1) (Field a2) = compare a1 a2 - -- | A `Generic` implementation of the `compare` member from the `Ord` type class. genericCompare :: forall a rep. Generic a rep => GenericOrd rep => a -> a -> Ordering genericCompare x y = genericCompare' (from x) (from y) diff --git a/src/Data/Generic/Rep/Semigroup.purs b/src/Data/Generic/Rep/Semigroup.purs index e36e5721..1ab5606a 100644 --- a/src/Data/Generic/Rep/Semigroup.purs +++ b/src/Data/Generic/Rep/Semigroup.purs @@ -26,12 +26,6 @@ instance genericSemigroupConstructor :: GenericSemigroup a => GenericSemigroup ( instance genericSemigroupArgument :: Semigroup a => GenericSemigroup (Argument a) where genericAppend' (Argument a1) (Argument a2) = Argument (append a1 a2) -instance genericSemigroupRec :: GenericSemigroup a => GenericSemigroup (Rec a) where - genericAppend' (Rec a1) (Rec a2) = Rec (genericAppend' a1 a2) - -instance genericSemigroupField :: Semigroup a => GenericSemigroup (Field name a) where - genericAppend' (Field a1) (Field a2) = Field (append a1 a2) - -- | A `Generic` implementation of the `append` member from the `Semigroup` type class. genericAppend :: forall a rep. Generic a rep => GenericSemigroup rep => a -> a -> a genericAppend x y = to (genericAppend' (from x) (from y)) diff --git a/src/Data/Generic/Rep/Show.purs b/src/Data/Generic/Rep/Show.purs index 9b64ff08..f7be7023 100644 --- a/src/Data/Generic/Rep/Show.purs +++ b/src/Data/Generic/Rep/Show.purs @@ -4,8 +4,6 @@ module Data.Generic.Rep.Show , genericShow , class GenericShowArgs , genericShowArgs - , class GenericShowFields - , genericShowFields ) where import Prelude (class Show, show, (<>)) @@ -19,9 +17,6 @@ class GenericShow a where class GenericShowArgs a where genericShowArgs :: a -> Array String -class GenericShowFields a where - genericShowFields :: a -> Array String - instance genericShowNoConstructors :: GenericShow NoConstructors where genericShow' a = genericShow' a @@ -37,11 +32,6 @@ instance genericShowArgsProduct => GenericShowArgs (Product a b) where genericShowArgs (Product a b) = genericShowArgs a <> genericShowArgs b -instance genericShowFieldsProduct - :: (GenericShowFields a, GenericShowFields b) - => GenericShowFields (Product a b) where - genericShowFields (Product a b) = genericShowFields a <> genericShowFields b - instance genericShowConstructor :: (GenericShowArgs a, IsSymbol name) => GenericShow (Constructor name a) where @@ -56,18 +46,6 @@ instance genericShowConstructor instance genericShowArgsArgument :: Show a => GenericShowArgs (Argument a) where genericShowArgs (Argument a) = [show a] -instance genericShowArgsRec :: GenericShowFields a => GenericShowArgs (Rec a) where - genericShowArgs (Rec a) = ["{ " <> intercalate ", " (genericShowFields a) <> " }"] - -instance genericShowFieldsField - :: (Show a, IsSymbol name) - => GenericShowFields (Field name a) where - genericShowFields (Field a) = - [reflectSymbol (SProxy :: SProxy name) <> ": " <> show a] - -instance genericShowFieldsNoArguments :: GenericShowFields NoArguments where - genericShowFields _ = [] - -- | A `Generic` implementation of the `show` member from the `Show` type class. genericShow :: forall a rep. Generic a rep => GenericShow rep => a -> String genericShow x = genericShow' (from x) From b9f0eec32ed35b71ca3e006a250ee140e2231f8f Mon Sep 17 00:00:00 2001 From: Liam Goodacre Date: Thu, 19 Apr 2018 12:19:40 +0100 Subject: [PATCH 14/33] Bump deps for compiler/0.12 --- test/Main.purs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/test/Main.purs b/test/Main.purs index 2dc987bf..1892da38 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -2,8 +2,8 @@ module Test.Main where import Prelude -import Control.Monad.Eff (Eff) -import Control.Monad.Eff.Console (CONSOLE, log, logShow) +import Effect (Effect) +import Effect.Console (log, logShow) import Data.Enum (class BoundedEnum, class Enum, Cardinality(..), cardinality, fromEnum, pred, succ, toEnum, enumFromTo) import Data.Generic.Rep as G import Data.Generic.Rep.Bounded as GBounded @@ -12,7 +12,7 @@ import Data.Generic.Rep.Eq as GEq import Data.Generic.Rep.Ord as GOrd import Data.Generic.Rep.Show as GShow import Data.Maybe (Maybe(..)) -import Test.Assert (ASSERT, assert) +import Test.Assert (assert) data List a = Nil | Cons { head :: a, tail :: List a } @@ -105,9 +105,8 @@ instance boundedEnumPair :: (BoundedEnum a, BoundedEnum b) => BoundedEnum (Pair cardinality = GEnum.genericCardinality toEnum = GEnum.genericToEnum fromEnum = GEnum.genericFromEnum - -main :: Eff (console :: CONSOLE, assert :: ASSERT) Unit +main :: Effect Unit main = do logShow (cons 1 (cons 2 Nil)) From bc43932f72883a7e4cb763804622d4076f4894a7 Mon Sep 17 00:00:00 2001 From: Liam Goodacre Date: Wed, 25 Apr 2018 21:36:38 +0100 Subject: [PATCH 15/33] Remove symbols and fix operator fixity issue --- test/Main.purs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Main.purs b/test/Main.purs index 1892da38..78d5e51f 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -198,4 +198,4 @@ main = do log "Checking product toEnum/fromEnum roundtrip" assert $ let allPairs = enumFromTo bottom top :: Array (Pair Bit SimpleBounded) - in toEnum <<< fromEnum <$> allPairs == Just <$> allPairs + in (toEnum <<< fromEnum <$> allPairs) == (Just <$> allPairs) From 0dcffa83251ad1eef725f316f98d558c081a7f55 Mon Sep 17 00:00:00 2001 From: Gary Burgess Date: Wed, 23 May 2018 21:14:04 +0100 Subject: [PATCH 16/33] Update dependencies, license --- test/Main.purs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/test/Main.purs b/test/Main.purs index 78d5e51f..5d1b5f69 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -24,9 +24,6 @@ derive instance genericList :: G.Generic (List a) _ instance eqList :: Eq a => Eq (List a) where eq x y = GEq.genericEq x y -instance ordList :: Ord a => Ord (List a) where - compare x y = GOrd.genericCompare x y - instance showList :: Show a => Show (List a) where show x = GShow.genericShow x @@ -117,13 +114,13 @@ main = do assert $ cons 1 (cons 2 Nil) /= cons 1 Nil log "Checking comparison EQ" - assert $ (cons 1 (cons 2 Nil) `compare` cons 1 (cons 2 Nil)) == EQ + assert $ (Pair Zero (Some One) `compare` Pair Zero (Some One)) == EQ log "Checking comparison GT" - assert $ (cons 1 (cons 2 Nil) `compare` cons 1 Nil) == GT + assert $ (Pair (Some One) Zero `compare` Pair (Some Zero) Zero) == GT log "Checking comparison LT" - assert $ (cons 1 Nil `compare` cons 1 (cons 2 Nil)) == LT + assert $ (Pair Zero One `compare` Pair One One) == LT log "Checking simple bottom" assert $ bottom == A From c564620679f50d3950eff2782f5c6796d144dff8 Mon Sep 17 00:00:00 2001 From: Denis Stoyanov Date: Mon, 30 Jul 2018 21:05:07 +0300 Subject: [PATCH 17/33] Added HeytingAlgebra, Semiring, Ring --- src/Data/Generic/Rep/HeytingAlgebra.purs | 70 ++++++++++++++++++++++++ src/Data/Generic/Rep/Ring.purs | 24 ++++++++ src/Data/Generic/Rep/Semiring.purs | 51 +++++++++++++++++ test/Main.purs | 69 ++++++++++++++++++++++- 4 files changed, 212 insertions(+), 2 deletions(-) create mode 100644 src/Data/Generic/Rep/HeytingAlgebra.purs create mode 100644 src/Data/Generic/Rep/Ring.purs create mode 100644 src/Data/Generic/Rep/Semiring.purs diff --git a/src/Data/Generic/Rep/HeytingAlgebra.purs b/src/Data/Generic/Rep/HeytingAlgebra.purs new file mode 100644 index 00000000..f2223d8c --- /dev/null +++ b/src/Data/Generic/Rep/HeytingAlgebra.purs @@ -0,0 +1,70 @@ +module Data.Generic.Rep.HeytingAlgebra where + +import Prelude + +import Data.Generic.Rep (class Generic, Argument(..), Constructor(..), NoArguments(..), Product(..), from, to) +import Data.HeytingAlgebra (ff, implies, tt) + +class GenericHeytingAlgebra a where + genericFF' :: a + genericTT' :: a + genericImplies' :: a -> a -> a + genericConj' :: a -> a -> a + genericDisj' :: a -> a -> a + genericNot' :: a -> a + +instance genericHeytingAlgebraNoArguments :: GenericHeytingAlgebra NoArguments where + genericFF' = NoArguments + genericTT' = NoArguments + genericImplies' _ _ = NoArguments + genericConj' _ _ = NoArguments + genericDisj' _ _ = NoArguments + genericNot' _ = NoArguments + +instance genericHeytingAlgebraArgument :: HeytingAlgebra a => GenericHeytingAlgebra (Argument a) where + genericFF' = Argument ff + genericTT' = Argument tt + genericImplies' (Argument x) (Argument y) = Argument (implies x y) + genericConj' (Argument x) (Argument y) = Argument (conj x y) + genericDisj' (Argument x) (Argument y) = Argument (disj x y) + genericNot' (Argument x) = Argument (not x) + +instance genericHeytingAlgebraProduct :: (GenericHeytingAlgebra a, GenericHeytingAlgebra b) => GenericHeytingAlgebra (Product a b) where + genericFF' = Product genericFF' genericFF' + genericTT' = Product genericTT' genericTT' + genericImplies' (Product a1 b1) (Product a2 b2) = Product (genericImplies' a1 a2) (genericImplies' b1 b2) + genericConj' (Product a1 b1) (Product a2 b2) = Product (genericConj' a1 a2) (genericConj' b1 b2) + genericDisj' (Product a1 b1) (Product a2 b2) = Product (genericDisj' a1 a2) (genericDisj' b1 b2) + genericNot' (Product a b) = Product (genericNot' a) (genericNot' b) + +instance genericHeytingAlgebraConstructor :: GenericHeytingAlgebra a => GenericHeytingAlgebra (Constructor name a) where + genericFF' = Constructor genericFF' + genericTT' = Constructor genericTT' + genericImplies' (Constructor a1) (Constructor a2) = Constructor (genericImplies' a1 a2) + genericConj' (Constructor a1) (Constructor a2) = Constructor (genericConj' a1 a2) + genericDisj' (Constructor a1) (Constructor a2) = Constructor (genericDisj' a1 a2) + genericNot' (Constructor a) = Constructor (genericNot' a) + +-- | A `Generic` implementation of the `ff` member from the `HeytingAlgebra` type class. +genericFF :: forall a rep. Generic a rep => GenericHeytingAlgebra rep => a +genericFF = to genericFF' + +-- | A `Generic` implementation of the `tt` member from the `HeytingAlgebra` type class. +genericTT :: forall a rep. Generic a rep => GenericHeytingAlgebra rep => a +genericTT = to genericTT' + +-- | A `Generic` implementation of the `implies` member from the `HeytingAlgebra` type class. +genericImplies :: forall a rep. Generic a rep => GenericHeytingAlgebra rep => a -> a -> a +genericImplies x y = to $ from x `genericImplies'` from y + +-- | A `Generic` implementation of the `conj` member from the `HeytingAlgebra` type class. +genericConj :: forall a rep. Generic a rep => GenericHeytingAlgebra rep => a -> a -> a +genericConj x y = to $ from x `genericConj'` from y + +-- | A `Generic` implementation of the `disj` member from the `HeytingAlgebra` type class. +genericDisj :: forall a rep. Generic a rep => GenericHeytingAlgebra rep => a -> a -> a +genericDisj x y = to $ from x `genericDisj'` from y + +-- | A `Generic` implementation of the `not` member from the `HeytingAlgebra` type class. +genericNot :: forall a rep. Generic a rep => GenericHeytingAlgebra rep => a -> a +genericNot x = to $ genericNot' (from x) \ No newline at end of file diff --git a/src/Data/Generic/Rep/Ring.purs b/src/Data/Generic/Rep/Ring.purs new file mode 100644 index 00000000..f5c73f33 --- /dev/null +++ b/src/Data/Generic/Rep/Ring.purs @@ -0,0 +1,24 @@ +module Data.Generic.Rep.Ring where + +import Prelude + +import Data.Generic.Rep (class Generic, Argument(..), Constructor(..), NoArguments(..), Product(..), from, to) + +class GenericRing a where + genericSub' :: a -> a -> a + +instance genericRingNoArguments :: GenericRing NoArguments where + genericSub' _ _ = NoArguments + +instance genericRingArgument :: Ring a => GenericRing (Argument a) where + genericSub' (Argument x) (Argument y) = Argument (sub x y) + +instance genericRingProduct :: (GenericRing a, GenericRing b) => GenericRing (Product a b) where + genericSub' (Product a1 b1) (Product a2 b2) = Product (genericSub' a1 a2) (genericSub' b1 b2) + +instance genericRingConstructor :: GenericRing a => GenericRing (Constructor name a) where + genericSub' (Constructor a1) (Constructor a2) = Constructor (genericSub' a1 a2) + +-- | A `Generic` implementation of the `sub` member from the `Ring` type class. +genericSub :: forall a rep. Generic a rep => GenericRing rep => a -> a -> a +genericSub x y = to $ from x `genericSub'` from y \ No newline at end of file diff --git a/src/Data/Generic/Rep/Semiring.purs b/src/Data/Generic/Rep/Semiring.purs new file mode 100644 index 00000000..b6b24123 --- /dev/null +++ b/src/Data/Generic/Rep/Semiring.purs @@ -0,0 +1,51 @@ +module Data.Generic.Rep.Semiring where + +import Prelude + +import Data.Generic.Rep (class Generic, Argument(..), Constructor(..), NoArguments(..), Product(..), from, to) + +class GenericSemiring a where + genericAdd' :: a -> a -> a + genericZero' :: a + genericMul' :: a -> a -> a + genericOne' :: a + +instance genericSemiringNoArguments :: GenericSemiring NoArguments where + genericAdd' _ _ = NoArguments + genericZero' = NoArguments + genericMul' _ _ = NoArguments + genericOne' = NoArguments + +instance genericSemiringArgument :: Semiring a => GenericSemiring (Argument a) where + genericAdd' (Argument x) (Argument y) = Argument (add x y) + genericZero' = Argument zero + genericMul' (Argument x) (Argument y) = Argument (mul x y) + genericOne' = Argument one + +instance genericSemiringProduct :: (GenericSemiring a, GenericSemiring b) => GenericSemiring (Product a b) where + genericAdd' (Product a1 b1) (Product a2 b2) = Product (genericAdd' a1 a2) (genericAdd' b1 b2) + genericZero' = Product genericZero' genericZero' + genericMul' (Product a1 b1) (Product a2 b2) = Product (genericMul' a1 a2) (genericMul' b1 b2) + genericOne' = Product genericOne' genericOne' + +instance genericSemiringConstructor :: GenericSemiring a => GenericSemiring (Constructor name a) where + genericAdd' (Constructor a1) (Constructor a2) = Constructor (genericAdd' a1 a2) + genericZero' = Constructor genericZero' + genericMul' (Constructor a1) (Constructor a2) = Constructor (genericMul' a1 a2) + genericOne' = Constructor genericOne' + +-- | A `Generic` implementation of the `zero` member from the `Semiring` type class. +genericZero :: forall a rep. Generic a rep => GenericSemiring rep => a +genericZero = to genericZero' + +-- | A `Generic` implementation of the `one` member from the `Semiring` type class. +genericOne :: forall a rep. Generic a rep => GenericSemiring rep => a +genericOne = to genericOne' + +-- | A `Generic` implementation of the `add` member from the `Semiring` type class. +genericAdd :: forall a rep. Generic a rep => GenericSemiring rep => a -> a -> a +genericAdd x y = to $ from x `genericAdd'` from y + +-- | A `Generic` implementation of the `mul` member from the `Semiring` type class. +genericMul :: forall a rep. Generic a rep => GenericSemiring rep => a -> a -> a +genericMul x y = to $ from x `genericMul'` from y \ No newline at end of file diff --git a/test/Main.purs b/test/Main.purs index 5d1b5f69..085e7277 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -2,16 +2,21 @@ module Test.Main where import Prelude -import Effect (Effect) -import Effect.Console (log, logShow) import Data.Enum (class BoundedEnum, class Enum, Cardinality(..), cardinality, fromEnum, pred, succ, toEnum, enumFromTo) import Data.Generic.Rep as G import Data.Generic.Rep.Bounded as GBounded import Data.Generic.Rep.Enum as GEnum import Data.Generic.Rep.Eq as GEq +import Data.Generic.Rep.HeytingAlgebra as GHeytingAlgebra import Data.Generic.Rep.Ord as GOrd +import Data.Generic.Rep.Ring as GRing +import Data.Generic.Rep.Semiring as GSemiring import Data.Generic.Rep.Show as GShow +import Data.HeytingAlgebra (ff, tt) import Data.Maybe (Maybe(..)) +import Data.Tuple (Tuple(..)) +import Effect (Effect) +import Effect.Console (log, logShow) import Test.Assert (assert) data List a = Nil | Cons { head :: a, tail :: List a } @@ -103,6 +108,36 @@ instance boundedEnumPair :: (BoundedEnum a, BoundedEnum b) => BoundedEnum (Pair toEnum = GEnum.genericToEnum fromEnum = GEnum.genericFromEnum +data A1 = A1 (Tuple (Tuple Int {a :: Int}) {a :: Int}) +derive instance genericA1 :: G.Generic A1 _ +instance eqA1 :: Eq A1 where + eq a = GEq.genericEq a +instance showA1 :: Show A1 where + show a = GShow.genericShow a +instance semiringA1 :: Semiring A1 where + zero = GSemiring.genericZero + one = GSemiring.genericOne + add x y = GSemiring.genericAdd x y + mul x y = GSemiring.genericMul x y +instance ringA1 :: Ring A1 where + sub x y = GRing.genericSub x y + +data B1 = B1 (Tuple (Tuple Boolean {a :: Boolean}) {a :: Boolean}) +derive instance genericB1 :: G.Generic B1 _ +instance eqB1 :: Eq B1 where + eq a = GEq.genericEq a +instance showB1 :: Show B1 where + show a = GShow.genericShow a +instance heytingAlgebraB1 :: HeytingAlgebra B1 where + ff = GHeytingAlgebra.genericFF + tt = GHeytingAlgebra.genericTT + implies x y = GHeytingAlgebra.genericImplies x y + conj x y = GHeytingAlgebra.genericConj x y + disj x y = GHeytingAlgebra.genericDisj x y + not x = GHeytingAlgebra.genericNot x + +instance booleanAlgebraB1 :: BooleanAlgebra B1 + main :: Effect Unit main = do logShow (cons 1 (cons 2 Nil)) @@ -196,3 +231,33 @@ main = do log "Checking product toEnum/fromEnum roundtrip" assert $ let allPairs = enumFromTo bottom top :: Array (Pair Bit SimpleBounded) in (toEnum <<< fromEnum <$> allPairs) == (Just <$> allPairs) + + log "Checking zero" + assert $ (zero :: A1) == A1 (Tuple (Tuple 0 {a: 0}) {a: 0}) + + log "Checking one" + assert $ (one :: A1) == A1 (Tuple (Tuple 1 {a: 1}) {a: 1}) + + log "Checking add" + assert $ A1 (Tuple (Tuple 100 {a: 10}) {a: 20}) + A1 (Tuple (Tuple 50 {a: 30}) {a: 40}) == A1 (Tuple (Tuple 150 {a: 40}) {a: 60}) + + log "Checking mul" + assert $ A1 (Tuple (Tuple 100 {a: 10}) {a: 20}) * A1 (Tuple (Tuple 50 {a: 30}) {a: 40}) == A1 (Tuple (Tuple 5000 {a: 300}) {a: 800}) + + log "Checking sub" + assert $ A1 (Tuple (Tuple 100 {a: 10}) {a: 20}) - A1 (Tuple (Tuple 50 {a: 30}) {a: 40}) == A1 (Tuple (Tuple 50 {a: -20}) {a: -20}) + + log "Checking ff" + assert $ (ff :: B1) == B1 (Tuple (Tuple false {a: false}) {a: false}) + + log "Checking tt" + assert $ (tt :: B1) == B1 (Tuple (Tuple true {a: true}) {a: true}) + + log "Checking conj" + assert $ (B1 (Tuple (Tuple true {a: false}) {a: true}) && B1 (Tuple (Tuple false {a: false}) {a: true})) == B1 (Tuple (Tuple false { a: false }) { a: true }) + + log "Checking disj" + assert $ (B1 (Tuple (Tuple true {a: false}) {a: true}) || B1 (Tuple (Tuple false {a: false}) {a: true})) == B1 (Tuple (Tuple true { a: false }) { a: true }) + + log "Checking not" + assert $ not B1 (Tuple (Tuple true {a: false}) {a: true}) == B1 (Tuple (Tuple false {a: true}) {a: false}) \ No newline at end of file From 952627c72cc42f171f71610edd18a030d3c41bf5 Mon Sep 17 00:00:00 2001 From: Gary Burgess Date: Mon, 27 Apr 2020 17:47:57 +0100 Subject: [PATCH 18/33] Fix type annotation precedence in tests --- test/Main.purs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/Main.purs b/test/Main.purs index 085e7277..4ae7f7de 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -164,16 +164,16 @@ main = do assert $ top == D log "Checking composite bottom" - assert $ bottom == None :: Option SimpleBounded + assert $ bottom == (None :: Option SimpleBounded) log "Checking composite top" assert $ top == Some D log "Checking product bottom" - assert $ bottom == Pair Zero A :: Pair Bit SimpleBounded + assert $ bottom == (Pair Zero A :: Pair Bit SimpleBounded) log "Checking product top" - assert $ top == Pair One D :: Pair Bit SimpleBounded + assert $ top == (Pair One D :: Pair Bit SimpleBounded) log "Checking simple pred bottom" assert $ pred (bottom :: SimpleBounded) == Nothing From f7f498b56a31c29f2c7ba01c12e6a6969f73f536 Mon Sep 17 00:00:00 2001 From: Cyril Date: Wed, 25 Nov 2020 07:30:02 +0100 Subject: [PATCH 19/33] Replace monomorphic proxies by Type.Proxy.Proxy (#44) --- src/Data/Generic/Rep/Show.purs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Data/Generic/Rep/Show.purs b/src/Data/Generic/Rep/Show.purs index f7be7023..40b18715 100644 --- a/src/Data/Generic/Rep/Show.purs +++ b/src/Data/Generic/Rep/Show.purs @@ -9,7 +9,8 @@ module Data.Generic.Rep.Show import Prelude (class Show, show, (<>)) import Data.Foldable (intercalate) import Data.Generic.Rep -import Data.Symbol (class IsSymbol, SProxy(..), reflectSymbol) +import Data.Symbol (class IsSymbol, reflectSymbol) +import Type.Proxy (Proxy(..)) class GenericShow a where genericShow' :: a -> String @@ -41,7 +42,7 @@ instance genericShowConstructor args -> "(" <> intercalate " " ([ctor] <> args) <> ")" where ctor :: String - ctor = reflectSymbol (SProxy :: SProxy name) + ctor = reflectSymbol (Proxy :: Proxy name) instance genericShowArgsArgument :: Show a => GenericShowArgs (Argument a) where genericShowArgs (Argument a) = [show a] From 3e3fd193fb2230224547604bc18a25fb6c3b4db0 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 23 Dec 2020 09:48:05 -0800 Subject: [PATCH 20/33] Remove Generic Maybe instance --- src/Data/Generic/Rep.purs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/Data/Generic/Rep.purs b/src/Data/Generic/Rep.purs index 92bf8459..3c51da5f 100644 --- a/src/Data/Generic/Rep.purs +++ b/src/Data/Generic/Rep.purs @@ -36,13 +36,3 @@ newtype Argument a = Argument a class Generic a rep | a -> rep where to :: rep -> a from :: a -> rep - -instance genericMaybe - :: Generic (Maybe a) (Sum (Constructor "Nothing" NoArguments) - (Constructor "Just" (Argument a))) where - to (Inl _) = Nothing - to (Inr (Constructor (Argument a))) = Just a - - from Nothing = Inl (Constructor NoArguments) - from (Just a) = Inr (Constructor (Argument a)) - From f2f7ca82522a154a3eb0e5841dbc3b144b6a1015 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 23 Dec 2020 09:51:16 -0800 Subject: [PATCH 21/33] Remove Generic Enum from src and test --- src/Data/Generic/Rep/Enum.purs | 118 --------------------------------- test/Main.purs | 87 ------------------------ 2 files changed, 205 deletions(-) delete mode 100644 src/Data/Generic/Rep/Enum.purs diff --git a/src/Data/Generic/Rep/Enum.purs b/src/Data/Generic/Rep/Enum.purs deleted file mode 100644 index 594729cf..00000000 --- a/src/Data/Generic/Rep/Enum.purs +++ /dev/null @@ -1,118 +0,0 @@ -module Data.Generic.Rep.Enum where - -import Prelude - -import Data.Enum (class BoundedEnum, class Enum, Cardinality(..), cardinality, fromEnum, pred, succ, toEnum) -import Data.Generic.Rep (class Generic, Argument(..), Constructor(..), NoArguments(..), Product(..), Sum(..), from, to) -import Data.Generic.Rep.Bounded (class GenericBottom, class GenericTop, genericBottom', genericTop') -import Data.Maybe (Maybe(..)) -import Data.Newtype (unwrap) - -class GenericEnum a where - genericPred' :: a -> Maybe a - genericSucc' :: a -> Maybe a - -instance genericEnumNoArguments :: GenericEnum NoArguments where - genericPred' _ = Nothing - genericSucc' _ = Nothing - -instance genericEnumArgument :: Enum a => GenericEnum (Argument a) where - genericPred' (Argument a) = Argument <$> pred a - genericSucc' (Argument a) = Argument <$> succ a - -instance genericEnumConstructor :: GenericEnum a => GenericEnum (Constructor name a) where - genericPred' (Constructor a) = Constructor <$> genericPred' a - genericSucc' (Constructor a) = Constructor <$> genericSucc' a - -instance genericEnumSum :: (GenericEnum a, GenericTop a, GenericEnum b, GenericBottom b) => GenericEnum (Sum a b) where - genericPred' = case _ of - Inl a -> Inl <$> genericPred' a - Inr b -> case genericPred' b of - Nothing -> Just (Inl genericTop') - Just b' -> Just (Inr b') - genericSucc' = case _ of - Inl a -> case genericSucc' a of - Nothing -> Just (Inr genericBottom') - Just a' -> Just (Inl a') - Inr b -> Inr <$> genericSucc' b - -instance genericEnumProduct :: (GenericEnum a, GenericTop a, GenericBottom a, GenericEnum b, GenericTop b, GenericBottom b) => GenericEnum (Product a b) where - genericPred' (Product a b) = case genericPred' b of - Just p -> Just $ Product a p - Nothing -> flip Product genericTop' <$> genericPred' a - genericSucc' (Product a b) = case genericSucc' b of - Just s -> Just $ Product a s - Nothing -> flip Product genericBottom' <$> genericSucc' a - - --- | A `Generic` implementation of the `pred` member from the `Enum` type class. -genericPred :: forall a rep. Generic a rep => GenericEnum rep => a -> Maybe a -genericPred = map to <<< genericPred' <<< from - --- | A `Generic` implementation of the `succ` member from the `Enum` type class. -genericSucc :: forall a rep. Generic a rep => GenericEnum rep => a -> Maybe a -genericSucc = map to <<< genericSucc' <<< from - -class GenericBoundedEnum a where - genericCardinality' :: Cardinality a - genericToEnum' :: Int -> Maybe a - genericFromEnum' :: a -> Int - -instance genericBoundedEnumNoArguments :: GenericBoundedEnum NoArguments where - genericCardinality' = Cardinality 1 - genericToEnum' i = if i == 0 then Just NoArguments else Nothing - genericFromEnum' _ = 0 - -instance genericBoundedEnumArgument :: BoundedEnum a => GenericBoundedEnum (Argument a) where - genericCardinality' = Cardinality (unwrap (cardinality :: Cardinality a)) - genericToEnum' i = Argument <$> toEnum i - genericFromEnum' (Argument a) = fromEnum a - -instance genericBoundedEnumConstructor :: GenericBoundedEnum a => GenericBoundedEnum (Constructor name a) where - genericCardinality' = Cardinality (unwrap (genericCardinality' :: Cardinality a)) - genericToEnum' i = Constructor <$> genericToEnum' i - genericFromEnum' (Constructor a) = genericFromEnum' a - -instance genericBoundedEnumSum :: (GenericBoundedEnum a, GenericBoundedEnum b) => GenericBoundedEnum (Sum a b) where - genericCardinality' = - Cardinality - $ unwrap (genericCardinality' :: Cardinality a) - + unwrap (genericCardinality' :: Cardinality b) - genericToEnum' n = to genericCardinality' - where - to :: Cardinality a -> Maybe (Sum a b) - to (Cardinality ca) - | n >= 0 && n < ca = Inl <$> genericToEnum' n - | otherwise = Inr <$> genericToEnum' (n - ca) - genericFromEnum' = case _ of - Inl a -> genericFromEnum' a - Inr b -> genericFromEnum' b + unwrap (genericCardinality' :: Cardinality a) - - -instance genericBoundedEnumProduct :: (GenericBoundedEnum a, GenericBoundedEnum b) => GenericBoundedEnum (Product a b) where - genericCardinality' = - Cardinality - $ unwrap (genericCardinality' :: Cardinality a) - * unwrap (genericCardinality' :: Cardinality b) - genericToEnum' n = to genericCardinality' - where to :: Cardinality b -> Maybe (Product a b) - to (Cardinality cb) = Product <$> (genericToEnum' $ n `div` cb) <*> (genericToEnum' $ n `mod` cb) - genericFromEnum' = from genericCardinality' - where from :: Cardinality b -> (Product a b) -> Int - from (Cardinality cb) (Product a b) = genericFromEnum' a * cb + genericFromEnum' b - - --- | A `Generic` implementation of the `cardinality` member from the --- | `BoundedEnum` type class. -genericCardinality :: forall a rep. Generic a rep => GenericBoundedEnum rep => Cardinality a -genericCardinality = Cardinality (unwrap (genericCardinality' :: Cardinality rep)) - --- | A `Generic` implementation of the `toEnum` member from the `BoundedEnum` --- | type class. -genericToEnum :: forall a rep. Generic a rep => GenericBoundedEnum rep => Int -> Maybe a -genericToEnum = map to <<< genericToEnum' - --- | A `Generic` implementation of the `fromEnum` member from the `BoundedEnum` --- | type class. -genericFromEnum :: forall a rep. Generic a rep => GenericBoundedEnum rep => a -> Int -genericFromEnum = genericFromEnum' <<< from diff --git a/test/Main.purs b/test/Main.purs index 4ae7f7de..879c2c59 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -2,10 +2,8 @@ module Test.Main where import Prelude -import Data.Enum (class BoundedEnum, class Enum, Cardinality(..), cardinality, fromEnum, pred, succ, toEnum, enumFromTo) import Data.Generic.Rep as G import Data.Generic.Rep.Bounded as GBounded -import Data.Generic.Rep.Enum as GEnum import Data.Generic.Rep.Eq as GEq import Data.Generic.Rep.HeytingAlgebra as GHeytingAlgebra import Data.Generic.Rep.Ord as GOrd @@ -43,13 +41,6 @@ instance showSimpleBounded :: Show SimpleBounded where instance boundedSimpleBounded :: Bounded SimpleBounded where bottom = GBounded.genericBottom top = GBounded.genericTop -instance enumSimpleBounded :: Enum SimpleBounded where - pred = GEnum.genericPred - succ = GEnum.genericSucc -instance boundedEnumSimpleBounded :: BoundedEnum SimpleBounded where - cardinality = GEnum.genericCardinality - toEnum = GEnum.genericToEnum - fromEnum = GEnum.genericFromEnum data Option a = None | Some a derive instance genericOption :: G.Generic (Option a) _ @@ -62,13 +53,6 @@ instance showOption :: Show a => Show (Option a) where instance boundedOption :: Bounded a => Bounded (Option a) where bottom = GBounded.genericBottom top = GBounded.genericTop -instance enumOption :: (Bounded a, Enum a) => Enum (Option a) where - pred = GEnum.genericPred - succ = GEnum.genericSucc -instance boundedEnumOption :: BoundedEnum a => BoundedEnum (Option a) where - cardinality = GEnum.genericCardinality - toEnum = GEnum.genericToEnum - fromEnum = GEnum.genericFromEnum data Bit = Zero | One derive instance genericBit :: G.Generic Bit _ @@ -81,13 +65,6 @@ instance showBit :: Show Bit where instance boundedBit :: Bounded Bit where bottom = GBounded.genericBottom top = GBounded.genericTop -instance enumBit :: Enum Bit where - pred = GEnum.genericPred - succ = GEnum.genericSucc -instance boundedEnumBit :: BoundedEnum Bit where - cardinality = GEnum.genericCardinality - toEnum = GEnum.genericToEnum - fromEnum = GEnum.genericFromEnum data Pair a b = Pair a b derive instance genericPair :: G.Generic (Pair a b) _ @@ -100,13 +77,6 @@ instance showPair :: (Show a, Show b) => Show (Pair a b) where instance boundedPair :: (Bounded a, Bounded b) => Bounded (Pair a b) where bottom = GBounded.genericBottom top = GBounded.genericTop -instance enumPair :: (Bounded a, Enum a, Bounded b, Enum b) => Enum (Pair a b) where - pred = GEnum.genericPred - succ = GEnum.genericSucc -instance boundedEnumPair :: (BoundedEnum a, BoundedEnum b) => BoundedEnum (Pair a b) where - cardinality = GEnum.genericCardinality - toEnum = GEnum.genericToEnum - fromEnum = GEnum.genericFromEnum data A1 = A1 (Tuple (Tuple Int {a :: Int}) {a :: Int}) derive instance genericA1 :: G.Generic A1 _ @@ -175,63 +145,6 @@ main = do log "Checking product top" assert $ top == (Pair One D :: Pair Bit SimpleBounded) - log "Checking simple pred bottom" - assert $ pred (bottom :: SimpleBounded) == Nothing - - log "Checking simple (pred =<< succ bottom)" - assert $ (pred =<< succ bottom) == Just A - - log "Checking simple succ top" - assert $ succ (top :: SimpleBounded) == Nothing - - log "Checking simple (succ =<< pred top)" - assert $ (succ =<< pred top) == Just D - - log "Checking composite pred bottom" - assert $ pred (bottom :: Option SimpleBounded) == Nothing - - log "Checking composite (pred =<< succ bottom)" - assert $ (pred =<< succ (bottom :: Option SimpleBounded)) == Just None - - log "Checking composite succ top" - assert $ succ (top :: Option SimpleBounded) == Nothing - - log "Checking composite (succ =<< pred top)" - assert $ (succ =<< pred top) == Just (Some D) - - log "Checking product pred bottom" - assert $ pred (bottom :: Pair Bit SimpleBounded) == Nothing - - log "Checking product (pred =<< succ bottom)" - assert $ (pred =<< succ (bottom :: Pair Bit SimpleBounded)) == Just (Pair Zero A) - - log "Checking product succ top" - assert $ succ (top :: Pair Bit SimpleBounded) == Nothing - - log "Checking product (succ =<< pred top)" - assert $ (succ =<< pred top) == Just (Pair One D) - - log "Checking simple cardinality" - assert $ (cardinality :: Cardinality SimpleBounded) == Cardinality 4 - - log "Checking composite cardinality" - assert $ (cardinality :: Cardinality (Option SimpleBounded)) == Cardinality 5 - - log "Checking product cardinality" - assert $ (cardinality :: Cardinality (Pair Bit SimpleBounded)) == Cardinality 8 - - log "Checking simple toEnum/fromEnum roundtrip" - assert $ toEnum (fromEnum A) == Just A - assert $ toEnum (fromEnum B) == Just B - - log "Checking composite toEnum/fromEnum roundtrip" - assert $ toEnum (fromEnum (None :: Option SimpleBounded)) == Just (None :: Option SimpleBounded) - assert $ toEnum (fromEnum (Some A)) == Just (Some A) - - log "Checking product toEnum/fromEnum roundtrip" - assert $ let allPairs = enumFromTo bottom top :: Array (Pair Bit SimpleBounded) - in (toEnum <<< fromEnum <$> allPairs) == (Just <$> allPairs) - log "Checking zero" assert $ (zero :: A1) == A1 (Tuple (Tuple 0 {a: 0}) {a: 0}) From 58bc915f6dddb530968449acb353a93330f7d6f2 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 23 Dec 2020 09:54:29 -0800 Subject: [PATCH 22/33] Move all files to their correct folders and rename files to Generic.purs --- src/Data/{Generic/Rep/Bounded.purs => Bounded/Generic.purs} | 0 src/Data/{Generic/Rep/Eq.purs => Eq/Generic.purs} | 0 .../Rep/HeytingAlgebra.purs => HeytingAlgebra/Generic.purs} | 0 src/Data/{Generic/Rep/Monoid.purs => Monoid/Generic.purs} | 0 src/Data/{Generic/Rep/Ord.purs => Ord/Generic.purs} | 0 src/Data/{Generic/Rep/Ring.purs => Ring/Generic.purs} | 0 src/Data/{Generic/Rep/Semigroup.purs => Semigroup/Generic.purs} | 0 src/Data/{Generic/Rep/Semiring.purs => Semiring/Generic.purs} | 0 src/Data/{Generic/Rep/Show.purs => Show/Generic.purs} | 0 9 files changed, 0 insertions(+), 0 deletions(-) rename src/Data/{Generic/Rep/Bounded.purs => Bounded/Generic.purs} (100%) rename src/Data/{Generic/Rep/Eq.purs => Eq/Generic.purs} (100%) rename src/Data/{Generic/Rep/HeytingAlgebra.purs => HeytingAlgebra/Generic.purs} (100%) rename src/Data/{Generic/Rep/Monoid.purs => Monoid/Generic.purs} (100%) rename src/Data/{Generic/Rep/Ord.purs => Ord/Generic.purs} (100%) rename src/Data/{Generic/Rep/Ring.purs => Ring/Generic.purs} (100%) rename src/Data/{Generic/Rep/Semigroup.purs => Semigroup/Generic.purs} (100%) rename src/Data/{Generic/Rep/Semiring.purs => Semiring/Generic.purs} (100%) rename src/Data/{Generic/Rep/Show.purs => Show/Generic.purs} (100%) diff --git a/src/Data/Generic/Rep/Bounded.purs b/src/Data/Bounded/Generic.purs similarity index 100% rename from src/Data/Generic/Rep/Bounded.purs rename to src/Data/Bounded/Generic.purs diff --git a/src/Data/Generic/Rep/Eq.purs b/src/Data/Eq/Generic.purs similarity index 100% rename from src/Data/Generic/Rep/Eq.purs rename to src/Data/Eq/Generic.purs diff --git a/src/Data/Generic/Rep/HeytingAlgebra.purs b/src/Data/HeytingAlgebra/Generic.purs similarity index 100% rename from src/Data/Generic/Rep/HeytingAlgebra.purs rename to src/Data/HeytingAlgebra/Generic.purs diff --git a/src/Data/Generic/Rep/Monoid.purs b/src/Data/Monoid/Generic.purs similarity index 100% rename from src/Data/Generic/Rep/Monoid.purs rename to src/Data/Monoid/Generic.purs diff --git a/src/Data/Generic/Rep/Ord.purs b/src/Data/Ord/Generic.purs similarity index 100% rename from src/Data/Generic/Rep/Ord.purs rename to src/Data/Ord/Generic.purs diff --git a/src/Data/Generic/Rep/Ring.purs b/src/Data/Ring/Generic.purs similarity index 100% rename from src/Data/Generic/Rep/Ring.purs rename to src/Data/Ring/Generic.purs diff --git a/src/Data/Generic/Rep/Semigroup.purs b/src/Data/Semigroup/Generic.purs similarity index 100% rename from src/Data/Generic/Rep/Semigroup.purs rename to src/Data/Semigroup/Generic.purs diff --git a/src/Data/Generic/Rep/Semiring.purs b/src/Data/Semiring/Generic.purs similarity index 100% rename from src/Data/Generic/Rep/Semiring.purs rename to src/Data/Semiring/Generic.purs diff --git a/src/Data/Generic/Rep/Show.purs b/src/Data/Show/Generic.purs similarity index 100% rename from src/Data/Generic/Rep/Show.purs rename to src/Data/Show/Generic.purs From 0aa77634c8a60811a67ae1d2d72dac512f260050 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 23 Dec 2020 09:58:13 -0800 Subject: [PATCH 23/33] Update module names to match their file names --- src/Data/Bounded/Generic.purs | 2 +- src/Data/Eq/Generic.purs | 2 +- src/Data/HeytingAlgebra/Generic.purs | 2 +- src/Data/Monoid/Generic.purs | 2 +- src/Data/Ord/Generic.purs | 2 +- src/Data/Ring/Generic.purs | 2 +- src/Data/Semigroup/Generic.purs | 2 +- src/Data/Semiring/Generic.purs | 2 +- src/Data/Show/Generic.purs | 2 +- test/Main.purs | 18 +++++++++--------- 10 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/Data/Bounded/Generic.purs b/src/Data/Bounded/Generic.purs index 8b1ec859..c7e2e2ed 100644 --- a/src/Data/Bounded/Generic.purs +++ b/src/Data/Bounded/Generic.purs @@ -1,4 +1,4 @@ -module Data.Generic.Rep.Bounded +module Data.Bounded.Generic ( class GenericBottom , genericBottom' , genericBottom diff --git a/src/Data/Eq/Generic.purs b/src/Data/Eq/Generic.purs index fe09ab0f..1c9e1386 100644 --- a/src/Data/Eq/Generic.purs +++ b/src/Data/Eq/Generic.purs @@ -1,4 +1,4 @@ -module Data.Generic.Rep.Eq +module Data.Eq.Generic ( class GenericEq , genericEq' , genericEq diff --git a/src/Data/HeytingAlgebra/Generic.purs b/src/Data/HeytingAlgebra/Generic.purs index f2223d8c..d42e0b65 100644 --- a/src/Data/HeytingAlgebra/Generic.purs +++ b/src/Data/HeytingAlgebra/Generic.purs @@ -1,4 +1,4 @@ -module Data.Generic.Rep.HeytingAlgebra where +module Data.HeytingAlgebra.Generic where import Prelude diff --git a/src/Data/Monoid/Generic.purs b/src/Data/Monoid/Generic.purs index 999b2f59..a73232df 100644 --- a/src/Data/Monoid/Generic.purs +++ b/src/Data/Monoid/Generic.purs @@ -1,4 +1,4 @@ -module Data.Generic.Rep.Monoid +module Data.Monoid.Generic ( class GenericMonoid , genericMempty' , genericMempty diff --git a/src/Data/Ord/Generic.purs b/src/Data/Ord/Generic.purs index ad7c45c7..c47aada4 100644 --- a/src/Data/Ord/Generic.purs +++ b/src/Data/Ord/Generic.purs @@ -1,4 +1,4 @@ -module Data.Generic.Rep.Ord +module Data.Ord.Generic ( class GenericOrd , genericCompare' , genericCompare diff --git a/src/Data/Ring/Generic.purs b/src/Data/Ring/Generic.purs index f5c73f33..27c38fd6 100644 --- a/src/Data/Ring/Generic.purs +++ b/src/Data/Ring/Generic.purs @@ -1,4 +1,4 @@ -module Data.Generic.Rep.Ring where +module Data.Ring.Generic where import Prelude diff --git a/src/Data/Semigroup/Generic.purs b/src/Data/Semigroup/Generic.purs index 1ab5606a..5591903d 100644 --- a/src/Data/Semigroup/Generic.purs +++ b/src/Data/Semigroup/Generic.purs @@ -1,4 +1,4 @@ -module Data.Generic.Rep.Semigroup +module Data.Semigroup.Generic ( class GenericSemigroup , genericAppend' , genericAppend diff --git a/src/Data/Semiring/Generic.purs b/src/Data/Semiring/Generic.purs index b6b24123..578023e7 100644 --- a/src/Data/Semiring/Generic.purs +++ b/src/Data/Semiring/Generic.purs @@ -1,4 +1,4 @@ -module Data.Generic.Rep.Semiring where +module Data.Semiring.Generic where import Prelude diff --git a/src/Data/Show/Generic.purs b/src/Data/Show/Generic.purs index 40b18715..faf9a6ca 100644 --- a/src/Data/Show/Generic.purs +++ b/src/Data/Show/Generic.purs @@ -1,4 +1,4 @@ -module Data.Generic.Rep.Show +module Data.Show.Generic ( class GenericShow , genericShow' , genericShow diff --git a/test/Main.purs b/test/Main.purs index 879c2c59..759c6877 100644 --- a/test/Main.purs +++ b/test/Main.purs @@ -3,13 +3,13 @@ module Test.Main where import Prelude import Data.Generic.Rep as G -import Data.Generic.Rep.Bounded as GBounded -import Data.Generic.Rep.Eq as GEq -import Data.Generic.Rep.HeytingAlgebra as GHeytingAlgebra -import Data.Generic.Rep.Ord as GOrd -import Data.Generic.Rep.Ring as GRing -import Data.Generic.Rep.Semiring as GSemiring -import Data.Generic.Rep.Show as GShow +import Data.Bounded.Generic as GBounded +import Data.Eq.Generic as GEq +import Data.HeytingAlgebra.Generic as GHeytingAlgebra +import Data.Ord.Generic as GOrd +import Data.Ring.Generic as GRing +import Data.Semiring.Generic as GSemiring +import Data.Show.Generic as GShow import Data.HeytingAlgebra (ff, tt) import Data.Maybe (Maybe(..)) import Data.Tuple (Tuple(..)) @@ -158,7 +158,7 @@ main = do assert $ A1 (Tuple (Tuple 100 {a: 10}) {a: 20}) * A1 (Tuple (Tuple 50 {a: 30}) {a: 40}) == A1 (Tuple (Tuple 5000 {a: 300}) {a: 800}) log "Checking sub" - assert $ A1 (Tuple (Tuple 100 {a: 10}) {a: 20}) - A1 (Tuple (Tuple 50 {a: 30}) {a: 40}) == A1 (Tuple (Tuple 50 {a: -20}) {a: -20}) + assert $ A1 (Tuple (Tuple 100 {a: 10}) {a: 20}) - A1 (Tuple (Tuple 50 {a: 30}) {a: 40}) == A1 (Tuple (Tuple 50 {a: -20}) {a: -20}) log "Checking ff" assert $ (ff :: B1) == B1 (Tuple (Tuple false {a: false}) {a: false}) @@ -173,4 +173,4 @@ main = do assert $ (B1 (Tuple (Tuple true {a: false}) {a: true}) || B1 (Tuple (Tuple false {a: false}) {a: true})) == B1 (Tuple (Tuple true { a: false }) { a: true }) log "Checking not" - assert $ not B1 (Tuple (Tuple true {a: false}) {a: true}) == B1 (Tuple (Tuple false {a: true}) {a: false}) \ No newline at end of file + assert $ not B1 (Tuple (Tuple true {a: false}) {a: true}) == B1 (Tuple (Tuple false {a: true}) {a: false}) From d52cb7b0b520fbe109b0172b4bd16a7ad71352df Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 23 Dec 2020 10:00:35 -0800 Subject: [PATCH 24/33] Move test file for Data.Generic.Rep into proper folder and rename --- test/{Main.purs => Data/Generic/Rep.purs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/{Main.purs => Data/Generic/Rep.purs} (100%) diff --git a/test/Main.purs b/test/Data/Generic/Rep.purs similarity index 100% rename from test/Main.purs rename to test/Data/Generic/Rep.purs From 2e56ccb74b115b885e2e6db282a4345c1a626c2c Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 23 Dec 2020 10:01:04 -0800 Subject: [PATCH 25/33] Update generic-rep test file module to match file path --- test/Data/Generic/Rep.purs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Data/Generic/Rep.purs b/test/Data/Generic/Rep.purs index 759c6877..a9750332 100644 --- a/test/Data/Generic/Rep.purs +++ b/test/Data/Generic/Rep.purs @@ -1,4 +1,4 @@ -module Test.Main where +module Test.Data.Generic.Rep where import Prelude From 931a5549ef2a03aaff0b742b3054c2e589a833ad Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 23 Dec 2020 10:04:02 -0800 Subject: [PATCH 26/33] Rename generic-rep test name to testGenericRep --- test/Data/Generic/Rep.purs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Data/Generic/Rep.purs b/test/Data/Generic/Rep.purs index a9750332..067f4dc4 100644 --- a/test/Data/Generic/Rep.purs +++ b/test/Data/Generic/Rep.purs @@ -108,8 +108,8 @@ instance heytingAlgebraB1 :: HeytingAlgebra B1 where instance booleanAlgebraB1 :: BooleanAlgebra B1 -main :: Effect Unit -main = do +testGenericRep :: Effect Unit +testGenericRep = do logShow (cons 1 (cons 2 Nil)) log "Checking equality" From eeae3f9d30cd37a18134cbb1c4947d92b2ac2035 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 23 Dec 2020 10:06:23 -0800 Subject: [PATCH 27/33] Replace generic Show's Foldable.intercalate usage with FFI --- src/Data/Show/Generic.js | 14 ++++++++++++++ src/Data/Show/Generic.purs | 3 ++- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 src/Data/Show/Generic.js diff --git a/src/Data/Show/Generic.js b/src/Data/Show/Generic.js new file mode 100644 index 00000000..53338044 --- /dev/null +++ b/src/Data/Show/Generic.js @@ -0,0 +1,14 @@ +"use strict"; + +exports.intercalate = function (separator) { + return function (xs) { + var len = xs.length; + if (len === 0) return ""; + + var res = xs[0]; + for (var i = 1; i < len; i++) { + res = res + separator + xs[i]; + } + return res; + }; +}; diff --git a/src/Data/Show/Generic.purs b/src/Data/Show/Generic.purs index faf9a6ca..5a5f08fa 100644 --- a/src/Data/Show/Generic.purs +++ b/src/Data/Show/Generic.purs @@ -7,7 +7,6 @@ module Data.Show.Generic ) where import Prelude (class Show, show, (<>)) -import Data.Foldable (intercalate) import Data.Generic.Rep import Data.Symbol (class IsSymbol, reflectSymbol) import Type.Proxy (Proxy(..)) @@ -50,3 +49,5 @@ instance genericShowArgsArgument :: Show a => GenericShowArgs (Argument a) where -- | A `Generic` implementation of the `show` member from the `Show` type class. genericShow :: forall a rep. Generic a rep => GenericShow rep => a -> String genericShow x = genericShow' (from x) + +foreign import intercalate :: String -> Array String -> String From 60aa75aa623de5526879e897c52f3eed7fc2be6c Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 23 Dec 2020 10:08:09 -0800 Subject: [PATCH 28/33] Replace Tuple with Pair in Data.Generic.Rep tests --- test/Data/Generic/Rep.purs | 41 +++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/test/Data/Generic/Rep.purs b/test/Data/Generic/Rep.purs index 067f4dc4..7e4bf4e0 100644 --- a/test/Data/Generic/Rep.purs +++ b/test/Data/Generic/Rep.purs @@ -12,7 +12,6 @@ import Data.Semiring.Generic as GSemiring import Data.Show.Generic as GShow import Data.HeytingAlgebra (ff, tt) import Data.Maybe (Maybe(..)) -import Data.Tuple (Tuple(..)) import Effect (Effect) import Effect.Console (log, logShow) import Test.Assert (assert) @@ -77,8 +76,22 @@ instance showPair :: (Show a, Show b) => Show (Pair a b) where instance boundedPair :: (Bounded a, Bounded b) => Bounded (Pair a b) where bottom = GBounded.genericBottom top = GBounded.genericTop - -data A1 = A1 (Tuple (Tuple Int {a :: Int}) {a :: Int}) +instance semiringPair :: (Semiring a, Semiring b) => Semiring (Pair a b) where + add (Pair x1 y1) (Pair x2 y2) = Pair (add x1 x2) (add y1 y2) + one = Pair one one + mul (Pair x1 y1) (Pair x2 y2) = Pair (mul x1 x2) (mul y1 y2) + zero = Pair zero zero +instance ringPair :: (Ring a, Ring b) => Ring (Pair a b) where + sub (Pair x1 y1) (Pair x2 y2) = Pair (sub x1 x2) (sub y1 y2) +instance heytingAlgebraPair :: (HeytingAlgebra a, HeytingAlgebra b) => HeytingAlgebra (Pair a b) where + tt = Pair tt tt + ff = Pair ff ff + implies (Pair x1 y1) (Pair x2 y2) = Pair (x1 `implies` x2) (y1 `implies` y2) + conj (Pair x1 y1) (Pair x2 y2) = Pair (conj x1 x2) (conj y1 y2) + disj (Pair x1 y1) (Pair x2 y2) = Pair (disj x1 x2) (disj y1 y2) + not (Pair x y) = Pair (not x) (not y) + +data A1 = A1 (Pair (Pair Int {a :: Int}) {a :: Int}) derive instance genericA1 :: G.Generic A1 _ instance eqA1 :: Eq A1 where eq a = GEq.genericEq a @@ -92,7 +105,7 @@ instance semiringA1 :: Semiring A1 where instance ringA1 :: Ring A1 where sub x y = GRing.genericSub x y -data B1 = B1 (Tuple (Tuple Boolean {a :: Boolean}) {a :: Boolean}) +data B1 = B1 (Pair (Pair Boolean {a :: Boolean}) {a :: Boolean}) derive instance genericB1 :: G.Generic B1 _ instance eqB1 :: Eq B1 where eq a = GEq.genericEq a @@ -146,31 +159,31 @@ testGenericRep = do assert $ top == (Pair One D :: Pair Bit SimpleBounded) log "Checking zero" - assert $ (zero :: A1) == A1 (Tuple (Tuple 0 {a: 0}) {a: 0}) + assert $ (zero :: A1) == A1 (Pair (Pair 0 {a: 0}) {a: 0}) log "Checking one" - assert $ (one :: A1) == A1 (Tuple (Tuple 1 {a: 1}) {a: 1}) + assert $ (one :: A1) == A1 (Pair (Pair 1 {a: 1}) {a: 1}) log "Checking add" - assert $ A1 (Tuple (Tuple 100 {a: 10}) {a: 20}) + A1 (Tuple (Tuple 50 {a: 30}) {a: 40}) == A1 (Tuple (Tuple 150 {a: 40}) {a: 60}) + assert $ A1 (Pair (Pair 100 {a: 10}) {a: 20}) + A1 (Pair (Pair 50 {a: 30}) {a: 40}) == A1 (Pair (Pair 150 {a: 40}) {a: 60}) log "Checking mul" - assert $ A1 (Tuple (Tuple 100 {a: 10}) {a: 20}) * A1 (Tuple (Tuple 50 {a: 30}) {a: 40}) == A1 (Tuple (Tuple 5000 {a: 300}) {a: 800}) + assert $ A1 (Pair (Pair 100 {a: 10}) {a: 20}) * A1 (Pair (Pair 50 {a: 30}) {a: 40}) == A1 (Pair (Pair 5000 {a: 300}) {a: 800}) log "Checking sub" - assert $ A1 (Tuple (Tuple 100 {a: 10}) {a: 20}) - A1 (Tuple (Tuple 50 {a: 30}) {a: 40}) == A1 (Tuple (Tuple 50 {a: -20}) {a: -20}) + assert $ A1 (Pair (Pair 100 {a: 10}) {a: 20}) - A1 (Pair (Pair 50 {a: 30}) {a: 40}) == A1 (Pair (Pair 50 {a: -20}) {a: -20}) log "Checking ff" - assert $ (ff :: B1) == B1 (Tuple (Tuple false {a: false}) {a: false}) + assert $ (ff :: B1) == B1 (Pair (Pair false {a: false}) {a: false}) log "Checking tt" - assert $ (tt :: B1) == B1 (Tuple (Tuple true {a: true}) {a: true}) + assert $ (tt :: B1) == B1 (Pair (Pair true {a: true}) {a: true}) log "Checking conj" - assert $ (B1 (Tuple (Tuple true {a: false}) {a: true}) && B1 (Tuple (Tuple false {a: false}) {a: true})) == B1 (Tuple (Tuple false { a: false }) { a: true }) + assert $ (B1 (Pair (Pair true {a: false}) {a: true}) && B1 (Pair (Pair false {a: false}) {a: true})) == B1 (Pair (Pair false { a: false }) { a: true }) log "Checking disj" - assert $ (B1 (Tuple (Tuple true {a: false}) {a: true}) || B1 (Tuple (Tuple false {a: false}) {a: true})) == B1 (Tuple (Tuple true { a: false }) { a: true }) + assert $ (B1 (Pair (Pair true {a: false}) {a: true}) || B1 (Pair (Pair false {a: false}) {a: true})) == B1 (Pair (Pair true { a: false }) { a: true }) log "Checking not" - assert $ not B1 (Tuple (Tuple true {a: false}) {a: true}) == B1 (Tuple (Tuple false {a: true}) {a: false}) + assert $ not B1 (Pair (Pair true {a: false}) {a: true}) == B1 (Pair (Pair false {a: true}) {a: false}) From 85d0fe6f674ef7d14dfbd462c5ad262daeedcab7 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 23 Dec 2020 10:09:18 -0800 Subject: [PATCH 29/33] Remove Maybe import from Data.Generic.Rep test file --- test/Data/Generic/Rep.purs | 1 - 1 file changed, 1 deletion(-) diff --git a/test/Data/Generic/Rep.purs b/test/Data/Generic/Rep.purs index 7e4bf4e0..90554a91 100644 --- a/test/Data/Generic/Rep.purs +++ b/test/Data/Generic/Rep.purs @@ -11,7 +11,6 @@ import Data.Ring.Generic as GRing import Data.Semiring.Generic as GSemiring import Data.Show.Generic as GShow import Data.HeytingAlgebra (ff, tt) -import Data.Maybe (Maybe(..)) import Effect (Effect) import Effect.Console (log, logShow) import Test.Assert (assert) From b6016995d09d6fcb846c7f008cecc5bcea55f79a Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 23 Dec 2020 10:14:33 -0800 Subject: [PATCH 30/33] Remove Maybe import from Data.Generic.Rep --- src/Data/Generic/Rep.purs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Data/Generic/Rep.purs b/src/Data/Generic/Rep.purs index 3c51da5f..45c4570e 100644 --- a/src/Data/Generic/Rep.purs +++ b/src/Data/Generic/Rep.purs @@ -10,8 +10,6 @@ module Data.Generic.Rep , Argument(..) ) where -import Data.Maybe (Maybe(..)) - -- | A representation for types with no constructors. data NoConstructors From 56493916b7803d3a7f8604940aa25ac5d2c94d6f Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 23 Dec 2020 10:21:57 -0800 Subject: [PATCH 31/33] Extract AlmostEff and assert to Test.Utils.purs file --- test/Test/Main.js | 6 ------ test/Test/Main.purs | 8 +------- test/Test/Utils.js | 7 +++++++ test/Test/Utils.purs | 10 ++++++++++ 4 files changed, 18 insertions(+), 13 deletions(-) create mode 100644 test/Test/Utils.js create mode 100644 test/Test/Utils.purs diff --git a/test/Test/Main.js b/test/Test/Main.js index 296fe776..f3989122 100644 --- a/test/Test/Main.js +++ b/test/Test/Main.js @@ -42,9 +42,3 @@ exports.testNumberShow = function(showNumber) { ]); }; }; - -exports.throwErr = function(msg) { - return function() { - throw new Error(msg); - } -} diff --git a/test/Test/Main.purs b/test/Test/Main.purs index 45c7a34a..7d4e558a 100644 --- a/test/Test/Main.purs +++ b/test/Test/Main.purs @@ -3,8 +3,7 @@ module Test.Main where import Prelude import Data.HeytingAlgebra (ff, tt, implies) import Data.Ord (abs) - -type AlmostEff = Unit -> Unit +import Test.Utils (AlmostEff, assert) main :: AlmostEff main = do @@ -16,11 +15,6 @@ main = do testRecordInstances foreign import testNumberShow :: (Number -> String) -> AlmostEff -foreign import throwErr :: String -> AlmostEff - - -assert :: String -> Boolean -> AlmostEff -assert msg condition = if condition then const unit else throwErr msg testOrd :: forall a. Ord a => Show a => a -> a -> Ordering -> AlmostEff testOrd x y ord = diff --git a/test/Test/Utils.js b/test/Test/Utils.js new file mode 100644 index 00000000..bea69b25 --- /dev/null +++ b/test/Test/Utils.js @@ -0,0 +1,7 @@ +"use strict"; + +exports.throwErr = function(msg) { + return function() { + throw new Error(msg); + }; +}; diff --git a/test/Test/Utils.purs b/test/Test/Utils.purs new file mode 100644 index 00000000..e58e4968 --- /dev/null +++ b/test/Test/Utils.purs @@ -0,0 +1,10 @@ +module Test.Utils where + +import Prelude + +type AlmostEff = Unit -> Unit + +assert :: String -> Boolean -> AlmostEff +assert msg condition = if condition then const unit else throwErr msg + +foreign import throwErr :: String -> AlmostEff From 5caa3b32c9ad66e028f583118c969ede41bcb2cd Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 23 Dec 2020 10:27:06 -0800 Subject: [PATCH 32/33] Update Data.Generic.Rep tests to use AlmostEff; include it in main tests --- test/Data/Generic/Rep.purs | 93 +++++++++++++++++++------------------- test/Test/Main.purs | 2 + 2 files changed, 48 insertions(+), 47 deletions(-) diff --git a/test/Data/Generic/Rep.purs b/test/Data/Generic/Rep.purs index 90554a91..de3022e6 100644 --- a/test/Data/Generic/Rep.purs +++ b/test/Data/Generic/Rep.purs @@ -11,9 +11,7 @@ import Data.Ring.Generic as GRing import Data.Semiring.Generic as GSemiring import Data.Show.Generic as GShow import Data.HeytingAlgebra (ff, tt) -import Effect (Effect) -import Effect.Console (log, logShow) -import Test.Assert (assert) +import Test.Utils (AlmostEff, assert) data List a = Nil | Cons { head :: a, tail :: List a } @@ -120,69 +118,70 @@ instance heytingAlgebraB1 :: HeytingAlgebra B1 where instance booleanAlgebraB1 :: BooleanAlgebra B1 -testGenericRep :: Effect Unit +testGenericRep :: AlmostEff testGenericRep = do - logShow (cons 1 (cons 2 Nil)) + assert "Checking show" $ + show (cons 1 (cons 2 Nil)) == "(Cons { head: 1, tail: (Cons { head: 2, tail: Nil }) })" - log "Checking equality" - assert $ cons 1 (cons 2 Nil) == cons 1 (cons 2 Nil) + assert "Checking equality" $ + cons 1 (cons 2 Nil) == cons 1 (cons 2 Nil) - log "Checking inequality" - assert $ cons 1 (cons 2 Nil) /= cons 1 Nil + assert "Checking inequality" $ + cons 1 (cons 2 Nil) /= cons 1 Nil - log "Checking comparison EQ" - assert $ (Pair Zero (Some One) `compare` Pair Zero (Some One)) == EQ + assert "Checking comparison EQ" $ + (Pair Zero (Some One) `compare` Pair Zero (Some One)) == EQ - log "Checking comparison GT" - assert $ (Pair (Some One) Zero `compare` Pair (Some Zero) Zero) == GT + assert "Checking comparison GT" $ + (Pair (Some One) Zero `compare` Pair (Some Zero) Zero) == GT - log "Checking comparison LT" - assert $ (Pair Zero One `compare` Pair One One) == LT + assert "Checking comparison LT" $ + (Pair Zero One `compare` Pair One One) == LT - log "Checking simple bottom" - assert $ bottom == A + assert "Checking simple bottom" $ + bottom == A - log "Checking simple top" - assert $ top == D + assert "Checking simple top" $ + top == D - log "Checking composite bottom" - assert $ bottom == (None :: Option SimpleBounded) + assert "Checking composite bottom" $ + bottom == (None :: Option SimpleBounded) - log "Checking composite top" - assert $ top == Some D + assert "Checking composite top" $ + top == Some D - log "Checking product bottom" - assert $ bottom == (Pair Zero A :: Pair Bit SimpleBounded) + assert "Checking product bottom" $ + bottom == (Pair Zero A :: Pair Bit SimpleBounded) - log "Checking product top" - assert $ top == (Pair One D :: Pair Bit SimpleBounded) + assert "Checking product top" $ + top == (Pair One D :: Pair Bit SimpleBounded) - log "Checking zero" - assert $ (zero :: A1) == A1 (Pair (Pair 0 {a: 0}) {a: 0}) + assert "Checking zero" $ + (zero :: A1) == A1 (Pair (Pair 0 {a: 0}) {a: 0}) - log "Checking one" - assert $ (one :: A1) == A1 (Pair (Pair 1 {a: 1}) {a: 1}) + assert "Checking one" $ + (one :: A1) == A1 (Pair (Pair 1 {a: 1}) {a: 1}) - log "Checking add" - assert $ A1 (Pair (Pair 100 {a: 10}) {a: 20}) + A1 (Pair (Pair 50 {a: 30}) {a: 40}) == A1 (Pair (Pair 150 {a: 40}) {a: 60}) + assert "Checking add" $ + A1 (Pair (Pair 100 {a: 10}) {a: 20}) + A1 (Pair (Pair 50 {a: 30}) {a: 40}) == A1 (Pair (Pair 150 {a: 40}) {a: 60}) - log "Checking mul" - assert $ A1 (Pair (Pair 100 {a: 10}) {a: 20}) * A1 (Pair (Pair 50 {a: 30}) {a: 40}) == A1 (Pair (Pair 5000 {a: 300}) {a: 800}) + assert "Checking mul" $ + A1 (Pair (Pair 100 {a: 10}) {a: 20}) * A1 (Pair (Pair 50 {a: 30}) {a: 40}) == A1 (Pair (Pair 5000 {a: 300}) {a: 800}) - log "Checking sub" - assert $ A1 (Pair (Pair 100 {a: 10}) {a: 20}) - A1 (Pair (Pair 50 {a: 30}) {a: 40}) == A1 (Pair (Pair 50 {a: -20}) {a: -20}) + assert "Checking sub" $ + A1 (Pair (Pair 100 {a: 10}) {a: 20}) - A1 (Pair (Pair 50 {a: 30}) {a: 40}) == A1 (Pair (Pair 50 {a: -20}) {a: -20}) - log "Checking ff" - assert $ (ff :: B1) == B1 (Pair (Pair false {a: false}) {a: false}) + assert "Checking ff" $ + (ff :: B1) == B1 (Pair (Pair false {a: false}) {a: false}) - log "Checking tt" - assert $ (tt :: B1) == B1 (Pair (Pair true {a: true}) {a: true}) + assert "Checking tt" $ + (tt :: B1) == B1 (Pair (Pair true {a: true}) {a: true}) - log "Checking conj" - assert $ (B1 (Pair (Pair true {a: false}) {a: true}) && B1 (Pair (Pair false {a: false}) {a: true})) == B1 (Pair (Pair false { a: false }) { a: true }) + assert "Checking conj" $ + (B1 (Pair (Pair true {a: false}) {a: true}) && B1 (Pair (Pair false {a: false}) {a: true})) == B1 (Pair (Pair false { a: false }) { a: true }) - log "Checking disj" - assert $ (B1 (Pair (Pair true {a: false}) {a: true}) || B1 (Pair (Pair false {a: false}) {a: true})) == B1 (Pair (Pair true { a: false }) { a: true }) + assert "Checking disj" $ + (B1 (Pair (Pair true {a: false}) {a: true}) || B1 (Pair (Pair false {a: false}) {a: true})) == B1 (Pair (Pair true { a: false }) { a: true }) - log "Checking not" - assert $ not B1 (Pair (Pair true {a: false}) {a: true}) == B1 (Pair (Pair false {a: true}) {a: false}) + assert "Checking not" $ + not B1 (Pair (Pair true {a: false}) {a: true}) == B1 (Pair (Pair false {a: true}) {a: false}) diff --git a/test/Test/Main.purs b/test/Test/Main.purs index 7d4e558a..a3c0a806 100644 --- a/test/Test/Main.purs +++ b/test/Test/Main.purs @@ -3,6 +3,7 @@ module Test.Main where import Prelude import Data.HeytingAlgebra (ff, tt, implies) import Data.Ord (abs) +import Test.Data.Generic.Rep (testGenericRep) import Test.Utils (AlmostEff, assert) main :: AlmostEff @@ -13,6 +14,7 @@ main = do testIntDivMod testIntDegree testRecordInstances + testGenericRep foreign import testNumberShow :: (Number -> String) -> AlmostEff From f52d32877dee9edeec558cdfa1df247abdc9cb74 Mon Sep 17 00:00:00 2001 From: Jordan Martinez Date: Wed, 23 Dec 2020 10:33:14 -0800 Subject: [PATCH 33/33] Import implies in Data.Generic.Rep tests --- test/Data/Generic/Rep.purs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Data/Generic/Rep.purs b/test/Data/Generic/Rep.purs index de3022e6..385807a3 100644 --- a/test/Data/Generic/Rep.purs +++ b/test/Data/Generic/Rep.purs @@ -10,7 +10,7 @@ import Data.Ord.Generic as GOrd import Data.Ring.Generic as GRing import Data.Semiring.Generic as GSemiring import Data.Show.Generic as GShow -import Data.HeytingAlgebra (ff, tt) +import Data.HeytingAlgebra (ff, tt, implies) import Test.Utils (AlmostEff, assert) data List a = Nil | Cons { head :: a, tail :: List a }