parameterized 0.2.0.0 → 0.3.0.0
raw patch · 9 files changed
+80/−13 lines, 9 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Parameterized.Data.Monoid: type PMonoid n id t u v = (PMEmpty n id, PSemigroup n t u v)
+ Parameterized.Control.Monad.Trans.State.Strict: changingState :: (s -> m (a, t)) -> ChangingState m (s, t) a
+ Parameterized.Data.Monoid: class (PSemigroup n t u v, PMEmpty n id) => PMonoid n id t u v
+ Parameterized.Data.Monoid: instance forall k (n :: k -> GHC.Types.Type) (t :: k) (u :: k) (v :: k) (id :: k). (Parameterized.Data.Semigroup.PSemigroup n t u v, Parameterized.Data.Monoid.PMEmpty n id) => Parameterized.Data.Monoid.PMonoid n id t u v
Files
- README.md +11/−4
- parameterized.cabal +1/−1
- src/Parameterized/Control/Applicative.hs +8/−2
- src/Parameterized/Control/Monad.hs +1/−0
- src/Parameterized/Control/Monad/Trans/State/Strict.hs +7/−1
- src/Parameterized/Data/Monoid.hs +3/−1
- src/Parameterized/Data/Semigroup.hs +1/−0
- test/Parameterized/Control/Monad/Trans/Reader/ReaderSpec.hs +2/−2
- test/Parameterized/Control/Monad/Trans/State/Strict/StateSpec.hs +46/−2
README.md view
@@ -3,13 +3,20 @@ Parameterized/indexed monoids and monads using only a single parameter type variable. +Refer to [ReaderSpec.hs](https://github.com/louispan/parameterized/blob/master/test/Parameterized/Control/Monad/Trans/Reader/ReaderSpec.hs) and [StateSpec.hs](https://github.com/louispan/parameterized/blob/master/test/Parameterized/Control/Monad/Trans/State/Strict/StateSpec.hs) for example usages.+ # Changelog -* 0.1.0.0- - Initial version with parameterized Semigroup, Monoid, Applicative, Alternative, Monad- - Added instances for OverlappingWhichReader, DistinctWhichReader, ManyReader, ManyState, and ChangingState+* 0.3.0.0+ - PMonoid is now a class with a single instance (courtesy of georgew).+ - added fixities for backtick versions of pmappend, pappend, papply and pbind+ - added changingState constructor which results in better type inference. * 0.2.0.0 - Renamed Pempty to PEmpty.- - Added injective functional dependencies to PEmpty, and PEmpty.+ - Added injective functional dependencies to PMEmpty, and PEmpty. - TypeLevel is not exported by default++* 0.1.0.0+ - Initial version with parameterized Semigroup, Monoid, Applicative, Alternative, Monad+ - Added instances for OverlappingWhichReader, DistinctWhichReader, ManyReader, ManyState, and ChangingState
parameterized.cabal view
@@ -1,5 +1,5 @@ name: parameterized-version: 0.2.0.0+version: 0.3.0.0 synopsis: Extensible records and polymorphic variants. description: Parameterized/indexed monoids and monads using only a single parameter type variable.
src/Parameterized/Control/Applicative.hs view
@@ -23,6 +23,10 @@ -- | Parameterized version of 'pure' in 'Applicative' -- An instance of this should create a parameterized unary type -- where the parameter is an identity in respect to 'papply'+-- NB. For 'Parameterized.Control.Monad.Trans.State.Strict.ChangingState',+-- the id @s@ "parameter" cannot be purely determined from @m@,+-- so unlike 'pappend' there is not functional dependency to help type inference.+-- Hint: use @ppure \@_ \@_ @id@ to specify the id type to avoid ambiguity. class PPointed (m :: k -> Type -> Type) (id :: k) where -- | lift a value. ppure :: a -> m id a@@ -39,16 +43,17 @@ (&<*>) :: (PApplicative m t u v) => m t (a -> b) -> m u a -> m v b (&<*>) = papply infixl 4 &<*>+infixl 4 `papply` -- | Sequence actions, discarding the value of the first argument. (&*>) :: (PApplicative m t u v) => m t a -> m u b -> m v b a1 &*> a2 = (id <$ a1) &<*> a2-infixl 4 &<*+infixl 4 &*> -- | Sequence actions, discarding the value of the second argument. (&<*) :: (PApplicative m t u v) => m t a -> m u b -> m v a (&<*) = pliftA2 const-infixl 4 &*> -- , &<**>+infixl 4 &<* -- | Lift a function to actions. pliftA :: (Functor (m t)) => (a -> b) -> m t a -> m t b@@ -84,3 +89,4 @@ (&<|>) :: (PAlternative m t u v) => m t a -> m u a -> m v a (&<|>) = pappend infixl 3 &<|>+infixl 3 `pappend`
src/Parameterized/Control/Monad.hs view
@@ -26,6 +26,7 @@ (&>>=) :: PMonad m t u v => m t a -> (a -> m u b) -> m v b (&>>=) = pbind infixl 1 &>>=+infixl 1 `pbind` (&>>) :: PMonad m t u v => m t a -> m u b -> m v b m &>> k = m &>>= \_ -> k
src/Parameterized/Control/Monad/Trans/State/Strict.hs view
@@ -102,9 +102,15 @@ -- and another ChangingState that changes state from @t@ to @u@ -- make a State that changes from @s@ to @u@ -- with the compile time constraint that all the types in (AppendUnique a b) are distinct.+-- NB. The state is in the snd position to be consistent with StateT. newtype ChangingState m st a = ChangingState { runChangingState :: At0 st -> m (a, At1 st)- } deriving ( G.Generic)+ } deriving (G.Generic)++-- | Prefer this to using ChangingState to construct as it results in better type inference+-- as it avoids ambiguous type variable @st@+changingState :: (s -> m (a, t)) -> ChangingState m (s, t) a+changingState = ChangingState instance Functor m => Functor (ChangingState m st) where fmap f m = ChangingState $ \s ->
src/Parameterized/Data/Monoid.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE MultiParamTypeClasses #-}@@ -19,4 +20,5 @@ pmempty :: n id -- | Parameterized version of Monoid.-type PMonoid n id t u v = (PMEmpty n id, PSemigroup n t u v)+class (PSemigroup n t u v, PMEmpty n id) => PMonoid n id t u v+instance (PSemigroup n t u v, PMEmpty n id) => PMonoid n id t u v
src/Parameterized/Data/Semigroup.hs view
@@ -19,3 +19,4 @@ (&<>) :: (PSemigroup n t u v) => n t -> n u -> n v (&<>) = pmappend infixr 6 &<>+infixr 6 `pmappend`
test/Parameterized/Control/Monad/Trans/Reader/ReaderSpec.hs view
@@ -224,7 +224,7 @@ ManyReader manyBoolMaybeReader -- the "parameter" is combined r' = runManyReader r :: ReaderT (Many '[Int, Bool]) Maybe String- -- functionality of both readers in an Alternative fashion+ -- functionality of both readers in an Applicative fashion runReaderT r' ( (5 :: Int) ./ True ./ nil) `shouldBe` Just "5.True" runReaderT r' ( (5 :: Int) ./ False ./ nil) `shouldBe` Nothing runReaderT r' ( (0 :: Int) ./ True ./ nil) `shouldBe` Nothing@@ -238,7 +238,7 @@ _ -> empty -- the "parameter" is combined r' = runManyReader r :: ReaderT (Many '[Int, Bool]) Maybe String- -- functionality of both readers in an Applicative fashion+ -- functionality of both readers in an Monad fashion runReaderT r' ( (1 :: Int) ./ True ./ nil) `shouldBe` Just "True" runReaderT r' ( (1 :: Int) ./ False ./ nil) `shouldBe` Nothing runReaderT r' ( (5 :: Int) ./ True ./ nil) `shouldBe` Nothing
test/Parameterized/Control/Monad/Trans/State/Strict/StateSpec.hs view
@@ -8,7 +8,9 @@ import Parameterized.Control.Monad.Trans.State.Strict import Parameterized.Control.Monad import Data.Diverse+import Data.Functor.Identity import Data.Semigroup+import Text.Read (readMaybe) import Test.Hspec @@ -17,6 +19,10 @@ main :: IO () main = hspec spec +-- | NB. Normally you'd use @MaybeT (StateT s) r@ and not+-- @StateT s Maybe r@ because the state is lost on failure (Nothing),+-- but for the purposes of this test, I want test funtionality of @StateT s m@+-- where m is an Alternative. manyIntMaybeState :: StateT (Many '[Int]) Maybe String manyIntMaybeState= do s <- get@@ -39,6 +45,16 @@ -------------------------------- +intToString :: Int -> Identity (Bool, String)+intToString i = Identity (even i, show i)++stringToBool :: String -> Identity (Int, Bool)+stringToBool s = case readMaybe s of+ Nothing -> Identity (0, False)+ Just i -> Identity (i, True)++--------------------------------+ spec :: Spec spec = do @@ -72,7 +88,7 @@ ManyState manyBoolMaybeState -- the "parameter" is combined r' = runManyState r :: StateT (Many '[Int, Bool]) Maybe String- -- functionality of both readers in an Applicative fashion+ -- functionality of both state functions in an Applicative fashion runStateT r' ( (5 :: Int) ./ True ./ nil) `shouldBe` Just ("5.True", (6 :: Int) ./ False ./ nil) runStateT r' ( (5 :: Int) ./ False ./ nil) `shouldBe` Nothing runStateT r' ( (0 :: Int) ./ True ./ nil) `shouldBe` Nothing@@ -86,10 +102,38 @@ _ -> empty -- the "parameter" is combined r' = runManyState r :: StateT (Many '[Int, Bool]) Maybe String- -- functionality of both readers in an Monad fashion+ -- functionality of both state functions in an Monad fashion runStateT r' ( (1 :: Int) ./ True ./ nil) `shouldBe` Just ("True", (2 :: Int) ./ False ./ nil) runStateT r' ( (1 :: Int) ./ False ./ nil) `shouldBe` Nothing runStateT r' ( (5 :: Int) ./ True ./ nil) `shouldBe` Nothing runStateT r' ( (5 :: Int) ./ False ./ nil) `shouldBe` Nothing runStateT r' ( (0 :: Int) ./ True ./ nil) `shouldBe` Nothing runStateT r' ( (0 :: Int) ./ False ./ nil) `shouldBe` Nothing++ describe "ChangingState" $ do+ it "ppure id doesn't change the type of the parameter" $ do+ let r1 = (ppure @_ @_ @(Int, Int) id) &<*> changingState intToString+ -- the "parameter" doesn't change+ r1' = r1 :: ChangingState Identity (Int, String) Bool+ -- functionality unchanged+ runChangingState r1' (5 :: Int) `shouldBe` Identity (False, "5")+ runChangingState r1' (10 :: Int) `shouldBe` Identity (True, "10")++ it "it can 'papply' to combine state runners 'Applicative'ly" $ do+ let r = (\b i -> show b <> "." <> show i) <$> changingState intToString &<*>+ changingState stringToBool+ -- the "parameter" is combined+ r' = r :: ChangingState Identity (Int, Bool) String+ -- functionality of both state functions in an Applicative fashion+ runChangingState r' (5 :: Int) `shouldBe` Identity ("False.5", True)+ runChangingState r' (10 :: Int) `shouldBe` Identity ("True.10", True)++ it "it can 'pbind' to combine state runners 'Monad'ically" $ do+ let r = changingState intToString &>>= \b ->+ changingState stringToBool &>>= \i ->+ ppure @_ @_ @(Bool, Bool) (show b <> "." <> show i)+ -- the "parameter" is combined+ r' = r :: ChangingState Identity (Int, Bool) String+ -- functionality of both state functions in an Applicative fashion+ runChangingState r' (5 :: Int) `shouldBe` Identity ("False.5", True)+ runChangingState r' (10 :: Int) `shouldBe` Identity ("True.10", True)