free-functors 0.9 → 1.0
raw patch · 5 files changed
+142/−377 lines, 5 filesdep −constraints
Dependencies removed: constraints
Files
- free-functors.cabal +2/−6
- src/Data/Constraint/Class1.hs +0/−201
- src/Data/Functor/Free.hs +13/−27
- src/Data/Functor/Free/Internal.hs +127/−0
- src/Data/Functor/Free/TH.hs +0/−143
free-functors.cabal view
@@ -1,5 +1,5 @@ name: free-functors-version: 0.9+version: 1.0 synopsis: Free functors, adjoint to functors that forget class constraints. description: A free functor is a left adjoint to a forgetful functor. It used to be the case that the only category that was easy to work with in Haskell was Hask itself, so@@ -32,16 +32,13 @@ src exposed-modules:- Data.Constraint.Class1, Data.Functor.Cofree, Data.Functor.Free,+ Data.Functor.Free.Internal, Data.Functor.HCofree, Data.Functor.HFree, Data.Functor.HHCofree, Data.Functor.HHFree- - other-modules:- Data.Functor.Free.TH default-language: Haskell2010@@ -49,7 +46,6 @@ build-depends: base == 4.12.*, template-haskell == 2.14.*,- constraints == 0.10.*, transformers == 0.5.*, comonad == 5.*, algebraic-classes == 0.9.*,
− src/Data/Constraint/Class1.hs
@@ -1,201 +0,0 @@-{-# LANGUAGE- PolyKinds- , DataKinds- , RankNTypes- , TypeFamilies- , TypeOperators- , ConstraintKinds- , FlexibleContexts- , DefaultSignatures- , FlexibleInstances- , ScopedTypeVariables- , UndecidableInstances- , MultiParamTypeClasses- #-}--------------------------------------------------------------------------------- |--- Module : Data.Constraint.HasSuperClasses--- License : BSD-style (see the file LICENSE)------ Maintainer : sjoerd@w3future.com--- Stability : experimental--- Portability : non-portable-------------------------------------------------------------------------------module Data.Constraint.Class1 where--import Data.Constraint-import Data.Proxy-import Prelude hiding (id, (.))--import Control.Applicative-import Control.Arrow (Arrow, ArrowZero, ArrowPlus, ArrowLoop, ArrowApply, ArrowChoice)-import Control.Category-import Control.Comonad-import Data.Biapplicative-import Data.Functor.Contravariant-import Data.Functor.Contravariant.Divisible-import Data.Profunctor---- | Proof that @b@ is a superclass of @h@, i.e. @h x@ entails @b x@.-scls1 :: forall b h x. SuperClass1 b h => h x :- b x-scls1 = containsSelf . isSubset (Proxy :: Proxy x) (Proxy :: Proxy (SuperClasses b)) (Proxy :: Proxy (SuperClasses h)) . superClasses--type SuperClass1 b h = (HasSuperClasses h, HasSuperClasses b, SuperClasses b `Subset` SuperClasses h, IsSubset (SuperClasses b) (SuperClasses h))--class HasSuperClasses (c :: k -> Constraint) where- type SuperClasses c :: [k -> Constraint]- type SuperClasses c = '[c]- superClasses :: c x :- FoldConstraints (SuperClasses c) x- default superClasses :: (SuperClasses c ~ '[c]) => c x :- FoldConstraints (SuperClasses c) x- superClasses = Sub Dict- containsSelf :: FoldConstraints (SuperClasses c) x :- c x- default containsSelf :: (SuperClasses c ~ '[c]) => FoldConstraints (SuperClasses c) x :- c x- containsSelf = Sub Dict---instance HasSuperClasses Num-instance HasSuperClasses Eq-instance HasSuperClasses Enum-instance HasSuperClasses Bounded-instance HasSuperClasses Show-instance HasSuperClasses Read-instance HasSuperClasses Ord where- type SuperClasses Ord = Ord ': SuperClasses Eq- superClasses = Sub Dict- containsSelf = Sub Dict-instance HasSuperClasses Real where- type SuperClasses Real = Real ': SuperClasses Num ++ SuperClasses Ord- superClasses = Sub Dict- containsSelf = Sub Dict-instance HasSuperClasses Fractional where- type SuperClasses Fractional = Fractional ': SuperClasses Num- superClasses = Sub Dict- containsSelf = Sub Dict-instance HasSuperClasses Integral where- type SuperClasses Integral = Integral ': SuperClasses Real ++ SuperClasses Enum - superClasses = Sub Dict- containsSelf = Sub Dict-instance HasSuperClasses RealFrac where- type SuperClasses RealFrac = RealFrac ': SuperClasses Real ++ SuperClasses Fractional - superClasses = Sub Dict- containsSelf = Sub Dict-instance HasSuperClasses Floating where- type SuperClasses Floating = Floating ': SuperClasses Fractional - superClasses = Sub Dict- containsSelf = Sub Dict-instance HasSuperClasses RealFloat where- type SuperClasses RealFloat = RealFloat ': SuperClasses RealFrac ++ SuperClasses Floating - superClasses = Sub Dict- containsSelf = Sub Dict-instance HasSuperClasses Semigroup-instance HasSuperClasses Monoid where- type SuperClasses Monoid = Monoid ': SuperClasses Semigroup- superClasses = Sub Dict- containsSelf = Sub Dict--instance HasSuperClasses Functor-instance HasSuperClasses Applicative where- type SuperClasses Applicative = Applicative ': SuperClasses Functor- superClasses = Sub Dict- containsSelf = Sub Dict-instance HasSuperClasses Alternative where- type SuperClasses Alternative = Alternative ': SuperClasses Applicative- superClasses = Sub Dict- containsSelf = Sub Dict-instance HasSuperClasses Monad where- type SuperClasses Monad = Monad ': SuperClasses Applicative- superClasses = Sub Dict- containsSelf = Sub Dict-instance HasSuperClasses Foldable-instance HasSuperClasses Traversable where- type SuperClasses Traversable = Traversable ': SuperClasses Functor ++ SuperClasses Foldable- superClasses = Sub Dict- containsSelf = Sub Dict-instance HasSuperClasses Comonad where- type SuperClasses Comonad = Comonad ': SuperClasses Functor- superClasses = Sub Dict- containsSelf = Sub Dict--instance HasSuperClasses Contravariant-instance HasSuperClasses Divisible where- type SuperClasses Divisible = Divisible ': SuperClasses Contravariant- superClasses = Sub Dict- containsSelf = Sub Dict-instance HasSuperClasses Decidable where- type SuperClasses Decidable = Decidable ': SuperClasses Divisible- superClasses = Sub Dict- containsSelf = Sub Dict--instance HasSuperClasses Category-instance HasSuperClasses Arrow where- type SuperClasses Arrow = Arrow ': SuperClasses Category- superClasses = Sub Dict- containsSelf = Sub Dict-instance HasSuperClasses ArrowZero where- type SuperClasses ArrowZero = ArrowZero ': SuperClasses Arrow- superClasses = Sub Dict- containsSelf = Sub Dict-instance HasSuperClasses ArrowPlus where- type SuperClasses ArrowPlus = ArrowPlus ': SuperClasses ArrowZero- superClasses = Sub Dict- containsSelf = Sub Dict-instance HasSuperClasses ArrowChoice where- type SuperClasses ArrowChoice = ArrowChoice ': SuperClasses Arrow- superClasses = Sub Dict- containsSelf = Sub Dict-instance HasSuperClasses ArrowApply where- type SuperClasses ArrowApply = ArrowApply ': SuperClasses Arrow- superClasses = Sub Dict- containsSelf = Sub Dict-instance HasSuperClasses ArrowLoop where- type SuperClasses ArrowLoop = ArrowLoop ': SuperClasses Arrow- superClasses = Sub Dict- containsSelf = Sub Dict--instance HasSuperClasses Bifunctor-instance HasSuperClasses Biapplicative where- type SuperClasses Biapplicative = Biapplicative ': SuperClasses Bifunctor- superClasses = Sub Dict- containsSelf = Sub Dict--instance HasSuperClasses Profunctor-instance HasSuperClasses Strong where- type SuperClasses Strong = Strong ': SuperClasses Profunctor- superClasses = Sub Dict- containsSelf = Sub Dict-instance HasSuperClasses Choice where- type SuperClasses Choice = Choice ': SuperClasses Profunctor- superClasses = Sub Dict- containsSelf = Sub Dict-instance HasSuperClasses Closed where- type SuperClasses Closed = Closed ': SuperClasses Profunctor- superClasses = Sub Dict- containsSelf = Sub Dict---type family (++) (as :: [k]) (bs :: [k]) :: [k] where- (++) a '[] = a- (++) '[] b = b- (++) (a ': as) bs = a ': (as ++ bs)--type family FoldConstraints (cs :: [k -> Constraint]) (x :: k) :: Constraint-type instance FoldConstraints '[] x = ()-type instance FoldConstraints (c ': cs) x = (c x, FoldConstraints cs x)--class Elem (c :: k -> Constraint) (cs :: [k -> Constraint]) where- isElem :: Proxy cs -> FoldConstraints cs x :- c x-instance {-# OVERLAPPING #-} Elem c (c ': cs) where- isElem _ = weaken1-instance {-# OVERLAPPABLE #-} Elem b cs => Elem b (c ': cs) where- isElem _ = isElem (Proxy :: Proxy cs) . weaken2--class IsSubset as bs where- isSubset :: as `Subset` bs => Proxy x -> Proxy as -> Proxy bs -> FoldConstraints bs x :- FoldConstraints as x-instance IsSubset '[] bs where- isSubset _ _ _ = top-instance IsSubset as bs => IsSubset (a ': as) bs where- isSubset px _ pbs = isElem pbs &&& isSubset px (Proxy :: Proxy as) pbs--type family Subset (xs :: [k]) (ys :: [k]) :: Constraint-type instance Subset '[] bs = ()-type instance Subset (a ': as) bs = (Elem a bs, Subset as bs)
src/Data/Functor/Free.hs view
@@ -1,20 +1,16 @@ {-# OPTIONS_GHC -fno-warn-orphans #-} {-# LANGUAGE- ConstraintKinds- , GADTs- , RankNTypes+ TypeFamilies , TypeOperators- , FlexibleInstances- , MultiParamTypeClasses- , UndecidableInstances- , ScopedTypeVariables , DeriveFunctor , DeriveFoldable- , DeriveTraversable+ , ConstraintKinds , TemplateHaskell- , PolyKinds- , TypeFamilies- , DataKinds+ , DeriveTraversable+ , FlexibleInstances+ , UndecidableInstances+ , QuantifiedConstraints+ , MultiParamTypeClasses #-} ----------------------------------------------------------------------------- -- |@@ -60,9 +56,7 @@ import Data.Void -import Language.Haskell.TH.Syntax--import Data.Functor.Free.TH+import Data.Functor.Free.Internal -- | @unfold f = coproduct (unfold f) unit . f@ --@@ -101,16 +95,8 @@ initial = rightAdjunct absurd --- | Derive the instances of @`Free` c a@ for the class @c@, `Show`, `Foldable` and `Traversable`.------ For example:------ @deriveInstances ''Num@-deriveInstances :: Name -> Q [Dec]-deriveInstances = deriveInstances' True--deriveInstances' False ''Num-deriveInstances' False ''Fractional-deriveInstances' False ''Floating-deriveInstances' False ''Semigroup-deriveInstances' False ''Monoid+deriveInstances ''Num+deriveInstances ''Fractional+deriveInstances ''Floating+deriveInstances ''Semigroup+deriveInstances ''Monoid
+ src/Data/Functor/Free/Internal.hs view
@@ -0,0 +1,127 @@+{-# LANGUAGE+ RankNTypes+ , TypeOperators+ , DeriveFunctor+ , DeriveFoldable+ , ConstraintKinds+ , TemplateHaskell+ , DeriveTraversable+ , FlexibleInstances+ , ScopedTypeVariables+ , UndecidableInstances+ , QuantifiedConstraints+ , MultiParamTypeClasses+ , UndecidableSuperClasses+ #-}+module Data.Functor.Free.Internal where++import Control.Comonad+import Data.Algebra+import Data.Algebra.TH+import Language.Haskell.TH.Syntax+import Data.Traversable++-- | The free functor for class @c@.+--+-- @Free c a@ is basically an expression tree with operations from class @c@+-- and variables/placeholders of type @a@, created with `unit`.+-- Monadic bind allows you to replace each of these variables with another sub-expression.+newtype Free c a = Free { runFree :: forall b. c b => (a -> b) -> b }++-- | `unit` allows you to create @`Free` c@ values, together with the operations from the class @c@.+unit :: a -> Free c a+unit a = Free $ \k -> k a++-- | `rightAdjunct` is the destructor of @`Free` c@ values.+rightAdjunct :: c b => (a -> b) -> Free c a -> b+rightAdjunct f g = runFree g f++-- | @counit = rightAdjunct id@+counit :: c a => Free c a -> a+counit = rightAdjunct id++-- | @leftAdjunct f = f . unit@+leftAdjunct :: (Free c a -> b) -> a -> b+leftAdjunct f = f . unit++-- | @transform f as = as >>= f unit@+--+-- @transform f . transform g = transform (g . f)@+transform :: (forall r. c r => (b -> r) -> a -> r) -> Free c a -> Free c b+transform t (Free f) = Free (f . t)+++instance Functor (Free c) where+ fmap f = transform (. f)++instance Applicative (Free c) where+ pure = unit+ fs <*> as = transform (\k f -> rightAdjunct (k . f) as) fs++instance Monad (Free c) where+ return = unit+ as >>= f = transform (\k -> rightAdjunct k . f) as++newtype Extract a = Extract { getExtract :: a }+newtype Duplicate f a = Duplicate { getDuplicate :: f (f a) }+instance (forall x. c (Extract x), forall x. c (Duplicate (Free c) x))+ => Comonad (Free c) where+ extract = getExtract . rightAdjunct Extract+ duplicate = getDuplicate . rightAdjunct (Duplicate . unit . unit)+ ++class (Class f x) => Class' f x where evaluate' :: AlgebraSignature f => f x -> x+instance (Class f x) => Class' f x where evaluate' = evaluate++newtype LiftAFree c f a = LiftAFree { getLiftAFree :: f (Free c a) }++instance (forall x. c x => Class' f x) => Algebra f (Free c a) where+ algebra fa = Free $ \k -> evaluate' (fmap (rightAdjunct k) fa)+ +instance (Applicative f, forall x. c x => Class' s x) => Algebra s (LiftAFree c f a) where+ algebra = LiftAFree . fmap algebra . traverse getLiftAFree++instance (forall f x. Applicative f => c (LiftAFree c f x)) => Foldable (Free c) where+ foldMap = foldMapDefault++instance (forall f x. Applicative f => c (LiftAFree c f x)) => Traversable (Free c) where+ traverse f = getLiftAFree . rightAdjunct (LiftAFree . fmap unit . f)+++data ShowHelper f a = ShowUnit a | ShowRec (f (ShowHelper f a))++instance Algebra f (ShowHelper f a) where+ algebra = ShowRec++instance (Show a, Show (f (ShowHelper f a))) => Show (ShowHelper f a) where+ showsPrec p (ShowUnit a) = showParen (p > 10) $ showString "unit " . showsPrec 11 a+ showsPrec p (ShowRec f) = showsPrec p f++instance (Show a, Show (Signature c (ShowHelper (Signature c) a)), c (ShowHelper (Signature c) a)) => Show (Free c a) where+ showsPrec p = showsPrec p . rightAdjunct (ShowUnit :: a -> ShowHelper (Signature c) a)+++class (a => b) => a :=> b+instance (a => b) => a :=> b++-- | Derive the instances of @`Free` c a@ for the class @c@, `Show`, `Foldable` and `Traversable`.+--+-- For example:+--+-- @deriveInstances ''Num@+deriveInstances :: Name -> Q [Dec]+deriveInstances nm = getSignatureInfo nm >>= h where+ h sigInfo =+ concat <$> sequenceA+ [ deriveSignature nm+ , deriveInstanceWith_skipSignature freeHeader $ return []+ , deriveInstanceWith_skipSignature liftAFreeHeader $ return []+ , deriveInstanceWith_skipSignature showHelperHeader $ return []+ , deriveSuperclassInstances showHelperHeader+ ]+ where+ freeHeader = [t|forall a c. (forall x. c x :=> $clss x) => $clss (Free c a)|]+ liftAFreeHeader = [t|forall f a c. (Applicative f, forall x. c x :=> $clss x) => $clss (LiftAFree c f a)|]+ showHelperHeader = [t|forall a. $clss (ShowHelper $sig a)|]+ clss = pure $ ConT nm+ sig = pure . ConT $ signatureName sigInfo
− src/Data/Functor/Free/TH.hs
@@ -1,143 +0,0 @@-{-# LANGUAGE- ConstraintKinds- , GADTs- , RankNTypes- , TypeOperators- , FlexibleInstances- , MultiParamTypeClasses- , UndecidableInstances- , ScopedTypeVariables- , DeriveFunctor- , DeriveFoldable- , DeriveTraversable- , TemplateHaskell- , PolyKinds- , DataKinds- , QuantifiedConstraints- #-}-module Data.Functor.Free.TH where--import Data.Constraint hiding (Class)-import Data.Constraint.Class1--import Control.Comonad-import Data.Algebra-import Data.Algebra.TH-import Language.Haskell.TH.Syntax-import Data.Traversable---- | The free functor for class @c@.------ @Free c a@ is basically an expression tree with operations from class @c@--- and variables/placeholders of type @a@, created with `unit`.--- Monadic bind allows you to replace each of these variables with another sub-expression.-newtype Free c a = Free { runFree :: forall b. c b => (a -> b) -> b }---- | `unit` allows you to create @`Free` c@ values, together with the operations from the class @c@.-unit :: a -> Free c a-unit a = Free $ \k -> k a---- | `rightAdjunct` is the destructor of @`Free` c@ values.-rightAdjunct :: c b => (a -> b) -> Free c a -> b-rightAdjunct f g = runFree g f---- | @counit = rightAdjunct id@-counit :: c a => Free c a -> a-counit = rightAdjunct id---- | @leftAdjunct f = f . unit@-leftAdjunct :: (Free c a -> b) -> a -> b-leftAdjunct f = f . unit---- | @transform f as = as >>= f unit@------ @transform f . transform g = transform (g . f)@-transform :: (forall r. c r => (b -> r) -> a -> r) -> Free c a -> Free c b-transform t (Free f) = Free (f . t)---instance Functor (Free c) where- fmap f = transform (. f)--instance Applicative (Free c) where- pure = unit- fs <*> as = transform (\k f -> rightAdjunct (k . f) as) fs--instance Monad (Free c) where- return = unit- as >>= f = transform (\k -> rightAdjunct k . f) as--newtype Extract a = Extract { getExtract :: a }-newtype Duplicate f a = Duplicate { getDuplicate :: f (f a) }-instance (forall x. c (Extract x), forall x. c (Duplicate (Free c) x))- => Comonad (Free c) where- extract = getExtract . rightAdjunct Extract- duplicate = getDuplicate . rightAdjunct (Duplicate . unit . unit)- --class ForallLifted c where- dictLifted :: Applicative f => Dict (c (LiftAFree c f a))--rightAdjunctLifted :: (ForallLifted c, Applicative f) => (a -> LiftAFree c f b) -> Free c a -> LiftAFree c f b-rightAdjunctLifted = h dictLifted rightAdjunct- where- h :: Dict (c (t f b))- -> (c (t f b) => (a -> t f b) -> Free c a -> t f b)- -> (a -> t f b) -> Free c a -> t f b- h Dict f = f--newtype LiftAFree c f a = LiftAFree { getLiftAFree :: f (Free c a) }--instance SuperClass1 (Class f) c => Algebra f (Free c a) where- algebra fa = Free $ \k -> h scls1 (fmap (rightAdjunct k) fa)- where- h :: c b => (c b :- Class f b) -> f b -> b- h (Sub Dict) = evaluate- -instance (Applicative f, SuperClass1 (Class s) c) => Algebra s (LiftAFree c f a) where- algebra = LiftAFree . fmap algebra . traverse getLiftAFree--instance ForallLifted c => Foldable (Free c) where- foldMap = foldMapDefault--instance ForallLifted c => Traversable (Free c) where- traverse f = getLiftAFree . rightAdjunctLifted (LiftAFree . fmap unit . f)---data ShowHelper f a = ShowUnit a | ShowRec (f (ShowHelper f a))--instance Algebra f (ShowHelper f a) where- algebra = ShowRec--instance (Show a, Show (f (ShowHelper f a))) => Show (ShowHelper f a) where- showsPrec p (ShowUnit a) = showParen (p > 10) $ showString "unit " . showsPrec 11 a- showsPrec p (ShowRec f) = showsPrec p f--instance (Show a, Show (Signature c (ShowHelper (Signature c) a)), c (ShowHelper (Signature c) a)) => Show (Free c a) where- showsPrec p = showsPrec p . rightAdjunct (ShowUnit :: a -> ShowHelper (Signature c) a)---deriveInstances' :: Bool -> Name -> Q [Dec]-deriveInstances' withHSC nm = getSignatureInfo nm >>= h where- h sigInfo =- concat <$> sequenceA- [ deriveSignature nm- , deriveInstanceWith_skipSignature freeHeader $ return []- , deriveInstanceWith_skipSignature liftAFreeHeader $ return []- , deriveInstanceWith_skipSignature showHelperHeader $ return []- , deriveSuperclassInstances showHelperHeader- , hasSuperClassesInstance- , [d|instance ForallLifted $c where dictLifted = Dict|]- ]- where- freeHeader = [t|forall a vc. SuperClass1 $c vc => $c (Free vc a)|]- liftAFreeHeader = [t|forall f a vc. (Applicative f, SuperClass1 $c vc) => $c (LiftAFree vc f a)|]- showHelperHeader = [t|forall a. $c (ShowHelper $sig a)|]- hasSuperClassesInstance = if withHSC then [d|instance HasSuperClasses $c where {- type SuperClasses $c = $c ': $scs;- superClasses = Sub Dict;- containsSelf = Sub Dict- }|] else return []- scs = foldr (\(SuperclassTH scnm _ _) q -> [t|SuperClasses $(pure (ConT scnm)) ++ $q|]) [t|'[]|] $ superclasses sigInfo- c = pure $ ConT nm- sig = pure . ConT $ signatureName sigInfo