free-category 0.0.1.0 → 0.0.2.0
raw patch · 6 files changed
+125/−47 lines, 6 filesdep ~free-algebrassetup-changedPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependency ranges changed: free-algebras
API changes (from Hackage documentation)
- Control.Category.Free: instance Control.Category.Category (Control.Category.Free.Cat f)
- Control.Category.Free: instance Data.Monoid.MSet.MSet (Control.Category.Free.Cat f o o) (Control.Category.Free.Cat f a o)
- Control.Category.Free: instance Data.Semigroup.SSet.SSet (Control.Category.Free.Cat f o o) (Control.Category.Free.Cat f a o)
- Control.Category.Free: instance GHC.Base.Monoid (Control.Category.Free.Cat f o o)
- Control.Category.Free: instance GHC.Base.Semigroup (Control.Category.Free.Cat f o o)
- Control.Category.Free: instance forall k (f :: k -> k -> *) (o :: k) (a :: k). Data.Monoid.MSet.MSet (Control.Category.Free.C f o o) (Control.Category.Free.C f a o)
- Control.Category.Free: instance forall k (f :: k -> k -> *) (o :: k) (a :: k). Data.Semigroup.SSet.SSet (Control.Category.Free.C f o o) (Control.Category.Free.C f a o)
+ Control.Category.Free: instance forall k (f :: k -> k -> *) (o :: k). GHC.Base.Monoid (Control.Category.Free.Cat f o o)
+ Control.Category.Free: instance forall k (f :: k -> k -> *) (o :: k). GHC.Base.Semigroup (Control.Category.Free.Cat f o o)
+ Control.Category.Free: instance forall k (f :: k -> k -> *). Control.Category.Category (Control.Category.Free.Cat f)
+ Control.Category.FreeEff: [Base] :: c a b -> FreeEffCat m c a b
+ Control.Category.FreeEff: [Lift] :: m (FreeEffCat m c a b) -> FreeEffCat m c a b
+ Control.Category.FreeEff: class Category c => EffCategory c m | c -> m
+ Control.Category.FreeEff: data FreeEffCat :: (* -> *) -> (k -> k -> *) -> k -> k -> *
+ Control.Category.FreeEff: foldNatLift :: (Monad m, EffCategory c m) => (forall x y. tr x y -> c x y) -> FreeEffCat m (Cat tr) a b -> c a b
+ Control.Category.FreeEff: instance Control.Category.FreeEff.EffCategory (->) Data.Functor.Identity.Identity
+ Control.Category.FreeEff: instance GHC.Base.Monad m => Control.Algebra.Free2.FreeAlgebra2 (Control.Category.FreeEff.FreeEffCat m)
+ Control.Category.FreeEff: instance GHC.Base.Monad m => Control.Category.FreeEff.EffCategory (Control.Arrow.Kleisli m) m
+ Control.Category.FreeEff: instance forall k (m :: * -> *) (c :: k -> k -> *). (GHC.Base.Functor m, Control.Category.Category c) => Control.Category.Category (Control.Category.FreeEff.FreeEffCat m c)
+ Control.Category.FreeEff: instance forall k (m :: * -> *) (c :: k -> k -> *). (GHC.Base.Functor m, Control.Category.Category c) => Control.Category.FreeEff.EffCategory (Control.Category.FreeEff.FreeEffCat m c) m
+ Control.Category.FreeEff: lift :: EffCategory c m => m (c a b) -> c a b
+ Control.Category.FreeEff: liftCat :: Monad m => tr a b -> FreeEffCat m (Cat tr) a b
+ Control.Category.FreeEff: liftKleisli :: Applicative m => (a -> b) -> Kleisli m a b
- Control.Arrow.Free: bindFree2 :: (FreeAlgebra2 m, AlgebraType0 m g, AlgebraType0 m f) => m f a b -> (forall x y. () => f x y -> m g x y) -> m g a b
+ Control.Arrow.Free: bindFree2 :: (FreeAlgebra2 m, AlgebraType0 m g, AlgebraType0 m f) => m f a b -> (forall (x :: k) (y :: k). () => f x y -> m g x y) -> m g a b
- Control.Arrow.Free: class FreeAlgebra2 (m :: Type -> Type -> Type -> Type -> Type -> Type)
+ Control.Arrow.Free: class FreeAlgebra2 (m :: k -> k -> Type -> k -> k -> Type)
- Control.Arrow.Free: foldNatFree2 :: (FreeAlgebra2 m, AlgebraType m d, AlgebraType0 m f) => (forall x y. () => f x y -> d x y) -> m f a b -> d a b
+ Control.Arrow.Free: foldNatFree2 :: (FreeAlgebra2 m, AlgebraType m d, AlgebraType0 m f) => (forall (x :: k) (y :: k). () => f x y -> d x y) -> m f a b -> d a b
- Control.Arrow.Free: hoistFree2 :: (FreeAlgebra2 m, AlgebraType0 m g, AlgebraType0 m f) => (forall x y. () => f x y -> g x y) -> m f a b -> m g a b
+ Control.Arrow.Free: hoistFree2 :: (FreeAlgebra2 m, AlgebraType0 m g, AlgebraType0 m f) => (forall (x :: k) (y :: k). () => f x y -> g x y) -> m f a b -> m g a b
- Control.Category.Free: bindFree2 :: (FreeAlgebra2 m, AlgebraType0 m g, AlgebraType0 m f) => m f a b -> (forall x y. () => f x y -> m g x y) -> m g a b
+ Control.Category.Free: bindFree2 :: (FreeAlgebra2 m, AlgebraType0 m g, AlgebraType0 m f) => m f a b -> (forall (x :: k) (y :: k). () => f x y -> m g x y) -> m g a b
- Control.Category.Free: class FreeAlgebra2 (m :: Type -> Type -> Type -> Type -> Type -> Type)
+ Control.Category.Free: class FreeAlgebra2 (m :: k -> k -> Type -> k -> k -> Type)
- Control.Category.Free: data Cat :: (* -> * -> *) -> * -> * -> *
+ Control.Category.Free: data Cat :: (k -> k -> *) -> k -> k -> *
- Control.Category.Free: foldNatFree2 :: (FreeAlgebra2 m, AlgebraType m d, AlgebraType0 m f) => (forall x y. () => f x y -> d x y) -> m f a b -> d a b
+ Control.Category.Free: foldNatFree2 :: (FreeAlgebra2 m, AlgebraType m d, AlgebraType0 m f) => (forall (x :: k) (y :: k). () => f x y -> d x y) -> m f a b -> d a b
- Control.Category.Free: hoistFree2 :: (FreeAlgebra2 m, AlgebraType0 m g, AlgebraType0 m f) => (forall x y. () => f x y -> g x y) -> m f a b -> m g a b
+ Control.Category.Free: hoistFree2 :: (FreeAlgebra2 m, AlgebraType0 m g, AlgebraType0 m f) => (forall (x :: k) (y :: k). () => f x y -> g x y) -> m f a b -> m g a b
Files
- ChangeLog.md +5/−0
- README.md +18/−7
- Setup.hs +0/−2
- free-category.cabal +20/−19
- src/Control/Category/Free.hs +1/−19
- src/Control/Category/FreeEff.hs +81/−0
ChangeLog.md view
@@ -1,5 +1,10 @@ # Changelog for free-category +## Version 0.0.2.0++- EffCategory class and FreeEffCat category transformer+- Example usage of FreeEffCat+ ## Version 0.0.1.0 - free category (concrete and condensity transformed) - free arrows (concrete and condensity transformed)
README.md view
@@ -1,13 +1,24 @@ # Free Category [](http://github.com/coot)-[](https://travis-ci.org/coot/free-category)+[](https://circleci.com/gh/coot/free-category/tree/master) -This package introduces variouos encodings of free categories in Haskell.+This package introduces variouos presentations of free categories in Haskell. Free categories are useful to model state machines in a simple yet type safe way and for that purpose `Kleisli` categroies are a very useful target which-allows to include monadic computations. Read more-[here](https://coot.me/posts/finite-state-machines.html) on a simple example of-a finite state machine encoded using a free category using a simple GADT.-Another simple-[example](https://github.com/coot/free-algebras/blob/master/examples/src/Control/Category/Free.hs).+allows to include monadic computations. This packge contains a useful+generalisation of `Kliesli` categories captured by `EffCategory` class+(effectful categories), and a (free) transformer which lifts a category to+an effectful one.++## Some examples+* [LoginStateMachine](https://github.com/coot/free-category/blob/master/examples/src/LoginStateMachine.hs):+ based on [State Machines All The Way+ Down](https://www.youtube.com/watch?v=xq7ZuSRgCR4) by Edwin Bradly, 2017 You+ can run it with `cabal new-run examples:login-state-machine`.+* Read more [here](https://coot.me/posts/finite-state-machines.html) on+ a simple example of a finite state machine encoded using a free category+ using a simple GADT.+* Another+ [example](https://github.com/coot/free-algebras/blob/master/examples/src/Control/Category/Free.hs).+* [Blog post](https://coot.me/posts/kleisli-categories-and-free-monads.html) on Keleisli categories.
− Setup.hs
@@ -1,2 +0,0 @@-import Distribution.Simple-main = defaultMain
free-category.cabal view
@@ -1,5 +1,5 @@ name: free-category-version: 0.0.1.0+version: 0.0.2.0 synopsis: Free category description: Free categories category: Algebra, Control, Monads, Category@@ -24,31 +24,32 @@ exposed-modules: Control.Arrow.Free Control.Category.Free+ Control.Category.FreeEff other-modules: Paths_free_category hs-source-dirs: src default-extensions:- ConstraintKinds- DataKinds- DeriveFunctor- EmptyDataDecls- FlexibleInstances- FlexibleContexts- GADTs- KindSignatures- InstanceSigs- MultiParamTypeClasses- OverloadedStrings- PolyKinds- RankNTypes- ScopedTypeVariables- TupleSections- TypeApplications- TypeFamilies+ ConstraintKinds+ DataKinds+ DeriveFunctor+ EmptyDataDecls+ FlexibleInstances+ FlexibleContexts+ GADTs+ KindSignatures+ InstanceSigs+ MultiParamTypeClasses+ OverloadedStrings+ PolyKinds+ RankNTypes+ ScopedTypeVariables+ TupleSections+ TypeApplications+ TypeFamilies build-depends: base >= 4.9 && <5- , free-algebras >= 0.0.6.0+ , free-algebras >= 0.0.7.0 ghc-options: -Wall -fwarn-incomplete-record-updates
src/Control/Category/Free.hs view
@@ -37,8 +37,6 @@ import Data.Monoid (Monoid (..)) import Data.Semigroup (Semigroup (..)) #endif-import Data.Monoid.MSet (MSet (..))-import Data.Semigroup.SSet (SSet (..)) -- | -- Free category encoded as a recursive data type, in a simlar way as@@ -49,7 +47,7 @@ -- -- The same performance concerns that apply to @'Control.Monad.Free.Free'@ -- apply to this encoding of a free category.-data Cat :: (* -> * -> *) -> * -> * -> * where+data Cat :: (k -> k -> *) -> k -> k -> * where Id :: Cat f a a (:.:) :: f b c -> Cat f a b -> Cat f a c @@ -86,14 +84,6 @@ mappend = (<>) #endif -instance SSet (Cat f o o) (Cat f a o) where- act = (.)--instance MSet (Cat f o o) (Cat f a o) where-#if __GLASGOW_HASKELL__ < 804- mact = (.)-#endif- type instance AlgebraType0 Cat f = () type instance AlgebraType Cat c = Category c @@ -167,12 +157,4 @@ mempty = id #if __GLASGOW_HASKELL__ < 804 mappend = (<>)-#endif--instance SSet (C f o o) (C f a o) where- act = (.)--instance MSet (C f o o) (C f a o) where-#if __GLASGOW_HASKELL__ < 804- mact = (.) #endif
+ src/Control/Category/FreeEff.hs view
@@ -0,0 +1,81 @@+{-# LANGUAGE FunctionalDependencies #-}+module Control.Category.FreeEff+ ( EffCategory (..)+ , FreeEffCat (..)+ , liftCat+ , foldNatLift+ , liftKleisli+ ) where++import Prelude hiding (id, (.))++import Control.Arrow (Kleisli (..))+import Control.Category (Category (..))+import Data.Functor.Identity (Identity (..))++import Control.Category.Free (Cat (..))+import Control.Algebra.Free2 (FreeAlgebra2 (..))+import Data.Algebra.Free (AlgebraType, AlgebraType0, proof)+++-- | Categories which can lift monadic actions, i.e. effectful categories.+--+class Category c => EffCategory c m | c -> m where+ lift :: m (c a b) -> c a b++instance Monad m => EffCategory (Kleisli m) m where+ lift m = Kleisli (\a -> m >>= \(Kleisli f) -> f a)++instance EffCategory (->) Identity where+ lift = runIdentity++-- | Category transformer, which adds @'EffCategory'@ instance to the+-- underlying base category.+--+data FreeEffCat :: (* -> *) -> (k -> k -> *) -> k -> k -> * where+ Base :: c a b -> FreeEffCat m c a b+ Lift :: m (FreeEffCat m c a b) -> FreeEffCat m c a b++instance (Functor m, Category c) => Category (FreeEffCat m c) where+ id = Base id+ Base f . Base g = Base $ f . g+ f . Lift mg = Lift $ (f .) <$> mg+ Lift mf . g = Lift $ (. g) <$> mf++instance (Functor m, Category c) => EffCategory (FreeEffCat m c) m where+ lift = Lift++type instance AlgebraType0 (FreeEffCat m) c = (Monad m, Category c)+type instance AlgebraType (FreeEffCat m) c = EffCategory c m+instance Monad m => FreeAlgebra2 (FreeEffCat m) where+ liftFree2 = Base+ foldNatFree2 nat (Base cab) = nat cab+ foldNatFree2 nat (Lift mcab) = lift $ foldNatFree2 nat <$> mcab++ codom2 = proof+ forget2 = proof++-- | Wrap a transition into a free category @'Cat'@ and then in+-- @'FreeEffCat'@+--+-- prop> liftCat tr = Base (tr :.: Id)+--+liftCat :: Monad m => tr a b -> FreeEffCat m (Cat tr) a b+liftCat = liftFree2 . liftFree2++-- | Fold @'FreeLifing'@ category based on a free category @'Cat' tr@ using+-- a functor @tr x y -> c x y@.+--+foldNatLift+ :: (Monad m, EffCategory c m)+ => (forall x y. tr x y -> c x y)+ -> FreeEffCat m (Cat tr) a b+ -> c a b+foldNatLift nat = foldNatFree2 (foldNatFree2 nat)++-- | Functor from @'->'@ category to @'Kleisli' m@. If @m@ is @Identity@ then+-- it will respect @'lift'@ i.e. @liftKleisli (lift ar) = lift (liftKleisli <$>+-- ar).+--+liftKleisli :: Applicative m => (a -> b) -> Kleisli m a b+liftKleisli f = Kleisli (pure . f)