packages feed

free-category 0.0.2.0 → 0.0.3.0

raw patch · 7 files changed

+431/−78 lines, 7 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Control.Arrow.Free: [:.:] :: f b c -> Arr f a b -> Arr f a c
- Control.Category.Free: [:.:] :: f b c -> Cat f a b -> Cat f a c
- Control.Category.Free: infixr 9 :.:
+ Control.Arrow.Free: arrArr :: (b -> c) -> Arr f b c
+ Control.Arrow.Free: foldArr :: forall f arr a b. Arrow arr => (forall x y. f x y -> arr x y) -> Arr f a b -> arr a b
+ Control.Arrow.Free: instance GHC.Base.Monoid (Control.Arrow.Free.A f o o)
+ Control.Arrow.Free: instance GHC.Base.Monoid (Control.Arrow.Free.Arr f o o)
+ Control.Arrow.Free: instance GHC.Base.Semigroup (Control.Arrow.Free.A f o o)
+ Control.Arrow.Free: instance GHC.Base.Semigroup (Control.Arrow.Free.Arr f o o)
+ Control.Arrow.Free: mapArr :: f b c -> Arr f a b -> Arr f a c
+ Control.Category.Free: Op :: f b a -> Op
+ Control.Category.Free: [runOp] :: Op -> f b a
+ Control.Category.Free: arrCat :: forall (f :: k -> k -> *) a b. f a b -> Cat f a b
+ Control.Category.Free: foldCat :: forall f c a b. Category c => (forall x y. f x y -> c x y) -> Cat f a b -> c a b
+ Control.Category.Free: mapCat :: forall (f :: k -> k -> *) a b c. f b c -> Cat f a b -> Cat f a c
+ Control.Category.Free: newtype Op (f :: k -> k -> *) (a :: k) (b :: k)
+ Control.Category.Free.Internal: Op :: f b a -> Op
+ Control.Category.Free.Internal: [ConsTr] :: f b c -> ListTr f a b -> ListTr f a c
+ Control.Category.Free.Internal: [NilTr] :: ListTr f a a
+ Control.Category.Free.Internal: [runOp] :: Op -> f b a
+ Control.Category.Free.Internal: cons :: forall (f :: k -> k -> *) a b c. f b c -> Queue f a b -> Queue f a c
+ Control.Category.Free.Internal: data ListTr :: (k -> k -> *) -> k -> k -> *
+ Control.Category.Free.Internal: data Queue (f :: k -> k -> *) (a :: k) (b :: k)
+ Control.Category.Free.Internal: emptyQ :: Queue (f :: k -> k -> *) a a
+ Control.Category.Free.Internal: foldQ :: forall (f :: k -> k -> *) c a b. Category c => (forall x y. f x y -> c x y) -> Queue f a b -> c a b
+ Control.Category.Free.Internal: instance Control.Algebra.Free2.FreeAlgebra2 Control.Category.Free.Internal.ListTr
+ Control.Category.Free.Internal: instance Control.Arrow.Arrow f => Control.Arrow.Arrow (Control.Category.Free.Internal.ListTr f)
+ Control.Category.Free.Internal: instance Control.Arrow.ArrowChoice f => Control.Arrow.ArrowChoice (Control.Category.Free.Internal.ListTr f)
+ Control.Category.Free.Internal: instance Control.Arrow.ArrowZero f => Control.Arrow.ArrowZero (Control.Category.Free.Internal.ListTr f)
+ Control.Category.Free.Internal: instance forall k (f :: k -> k -> *) (o :: k). Control.Category.Category f => GHC.Base.Monoid (Control.Category.Free.Internal.Op f o o)
+ Control.Category.Free.Internal: instance forall k (f :: k -> k -> *) (o :: k). Control.Category.Category f => GHC.Base.Semigroup (Control.Category.Free.Internal.Op f o o)
+ Control.Category.Free.Internal: instance forall k (f :: k -> k -> *) (o :: k). GHC.Base.Monoid (Control.Category.Free.Internal.ListTr f o o)
+ Control.Category.Free.Internal: instance forall k (f :: k -> k -> *) (o :: k). GHC.Base.Semigroup (Control.Category.Free.Internal.ListTr f o o)
+ Control.Category.Free.Internal: instance forall k (f :: k -> k -> *). Control.Category.Category (Control.Category.Free.Internal.ListTr f)
+ Control.Category.Free.Internal: instance forall k (f :: k -> k -> *). Control.Category.Category f => Control.Category.Category (Control.Category.Free.Internal.Op f)
+ Control.Category.Free.Internal: newtype Op (f :: k -> k -> *) (a :: k) (b :: k)
+ Control.Category.Free.Internal: pattern ConsQ :: f b c -> Queue f a b -> Queue f a c
+ Control.Category.Free.Internal: pattern NilQ :: () => a ~ b => Queue f a b
+ Control.Category.Free.Internal: snoc :: forall (f :: k -> k -> *) a b c. Queue f b c -> f a b -> Queue f a c
+ Control.Category.Free.Internal: uncons :: Queue f a b -> ViewL f a b
+ Control.Category.Free.Internal: zipWithQ :: forall f g a b a' b'. Arrow f => (forall x y x' y'. f x y -> f x' y' -> f (g x x') (g y y')) -> Queue f a b -> Queue f a' b' -> Queue f (g a a') (g b b')
- Control.Category.Free: data Cat :: (k -> k -> *) -> k -> k -> *
+ Control.Category.Free: data Cat (f :: k -> k -> *) a b
- Control.Category.Free: fromC :: C f a b -> Cat f a b
+ Control.Category.Free: fromC :: C f a b -> ListTr f a b
- Control.Category.Free: toC :: Cat f a b -> C f a b
+ Control.Category.Free: toC :: ListTr f a b -> C f a b

Files

ChangeLog.md view
@@ -1,5 +1,12 @@ # Changelog for free-category +## Version 0.0.3.0+- Efficient 'Cat' and 'Aff' based on real time queues with scheduling+- Added Monoid instances +- Added Op category+- added `arrArr`, `mapArr`, `foldArr` for `Arr` free arrow category+- added `arrCat`, `mapCat`, `fodlMap` for `Cat` free categroy+ ## Version 0.0.2.0  - EffCategory class and FreeEffCat category transformer
README.md view
@@ -2,10 +2,15 @@ [![Maintainer: coot](https://img.shields.io/badge/maintainer-coot-lightgrey.svg)](http://github.com/coot) [![CircleCI](https://circleci.com/gh/coot/free-category/tree/master.svg?style=svg)](https://circleci.com/gh/coot/free-category/tree/master) -This package introduces variouos presentations of free categories in Haskell.+This package contains efficient free categories. There are two presentations: +* using realtime queues (C. Okasaki 'Pure Functional Data Structures')+* using continuation passing style++Free arrows and free Kleisli categories are also included.+ 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+manner.  For that purpose `Kleisli` categroies are a very useful target which 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
free-category.cabal view
@@ -1,5 +1,5 @@ name:           free-category-version:        0.0.2.0+version:        0.0.3.0 synopsis:       Free category description:    Free categories category:       Algebra, Control, Monads, Category@@ -7,7 +7,7 @@ bug-reports:    https://github.com/coot/free-category/issues author:         Marcin Szamotulski maintainer:     profunctor@pm.me-copyright:      (c) 2018 Marcin Szamotulski+copyright:      (c) 2018-2019 Marcin Szamotulski license:        MPL-2.0 license-file:   LICENSE build-type:     Simple@@ -15,6 +15,7 @@ extra-source-files:     ChangeLog.md     README.md+tested-with:    GHC==8.0.2, GHC==8.2.2, GHC==8.4.4, GHC==8.6.5  source-repository head   type: git@@ -24,29 +25,12 @@   exposed-modules:       Control.Arrow.Free       Control.Category.Free+      Control.Category.Free.Internal       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   build-depends:       base          >= 4.9 && <5     , free-algebras >= 0.0.7.0
src/Control/Arrow/Free.hs view
@@ -1,7 +1,21 @@-{-# LANGUAGE GADTs #-}+{-# LANGUAGE CPP                 #-}+{-# LANGUAGE GADTs               #-}+{-# LANGUAGE FlexibleInstances   #-}+{-# LANGUAGE InstanceSigs        #-}+{-# LANGUAGE PolyKinds           #-}+{-# LANGUAGE RankNTypes          #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies        #-}++{-# OPTIONS_HADDOCK show-extensions #-}+ module Control.Arrow.Free   ( -- * Free arrow-    Arr (..)+    Arr (Id, Arr, Prod)+  , arrArr+  , mapArr+  , foldArr+     -- * Free arrow (CPS style)   , A (..)   , fromA@@ -18,6 +32,11 @@ import           Prelude hiding (id, (.)) import           Control.Arrow (Arrow (..)) import           Control.Category (Category (..))+#if __GLASGOW_HASKELL__ < 804+import           Data.Monoid (Monoid (..))+import           Data.Semigroup (Semigroup (..))+#endif+ import           Control.Algebra.Free2   ( AlgebraType0   , AlgebraType@@ -30,23 +49,51 @@   , joinFree2   , bindFree2   )+import           Control.Category.Free.Internal  data Arr f a b where   Id    :: Arr f a a-  (:.:) :: f b c     -> Arr f a b -> Arr f a c+  Cons  :: f b c     -> Queue (Arr f) a b -> Arr f a c   Arr   :: (b -> c)  -> Arr f a b -> Arr f a c   Prod  :: Arr f a b -> Arr f a c -> Arr f a (b, c) +arrArr :: (b -> c) -> Arr f b c+arrArr bc = Arr bc Id++mapArr :: f b c+       -> Arr f a b+       -> Arr f a c+mapArr bc ac = Cons bc emptyQ . ac++foldArr :: forall f arr a b.+           Arrow arr+        => (forall x y. f x y -> arr x y)+        -> Arr f a b+        -> arr a b+foldArr _   Id = id+foldArr fun (Cons bc ab) = fun bc . foldQ (foldNatFree2 fun) ab+foldArr fun (Arr f g)    = arr f  . foldNatFree2 fun g+foldArr fun (Prod f g)   = foldNatFree2 fun f &&& foldNatFree2 fun g+ instance Category (Arr f) where   id = Id   Id         . f  = f   f          . Id = f-  (f :.: g)  . h  = f :.: (g . h)+  (Cons f g)  . h  = Cons f (g `snoc` h)   (Arr f g)  . h  = Arr f (g . h)   (Prod f g) . h  = Prod (f . h) (g . h) +instance Semigroup (Arr f o o) where+    f <> g = f . g++instance Monoid (Arr f o o) where+    mempty = Id+#if __GLASGOW_HASKELL__ < 804+    mappend = (<>)+#endif+ instance Arrow (Arr f) where-  arr f     = Arr f Id+  arr       = arrArr   first bc  = Prod (bc . arr fst) (arr snd)   second bc = Prod (arr fst) (bc . arr snd)   ab *** xy = Prod (ab . arr fst) (xy . arr snd)@@ -56,18 +103,21 @@ type instance AlgebraType  Arr c = Arrow c  instance FreeAlgebra2 Arr where-  liftFree2 = \fab -> fab :.: Id+  liftFree2 = \fab -> Cons fab emptyQ   {-# INLINE liftFree2 #-} -  foldNatFree2 _   Id = id-  foldNatFree2 fun (bc :.: ab) = fun bc . foldNatFree2 fun ab-  foldNatFree2 fun (Arr f g)   = arr f  . foldNatFree2 fun g-  foldNatFree2 fun (Prod f g)  = foldNatFree2 fun f &&& foldNatFree2 fun g+  foldNatFree2 = foldArr   {-# INLINE foldNatFree2 #-}    codom2  = proof   forget2 = proof +--+-- Free arrows using CSP style+--++-- | Free arrow using CPS sytle.+-- newtype A f a b   = A { runA :: forall r. Arrow r              => (forall x y. f x y -> r x y)@@ -90,6 +140,15 @@ instance Category (A f) where   id = A (const id)   A f . A g = A $ \k -> f k . g k++instance Semigroup (A f o o) where+    f <> g = f . g++instance Monoid (A f o o) where+    mempty = id+#if __GLASGOW_HASKELL__ < 804+    mappend = (<>)+#endif  instance Arrow (A f) where   arr f = A (const (arr f))
src/Control/Category/Free.hs view
@@ -1,12 +1,36 @@+{-# LANGUAGE BangPatterns       #-} {-# LANGUAGE CPP                #-}-{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE GADTs              #-}+{-# LANGUAGE FlexibleInstances  #-}+{-# LANGUAGE PatternSynonyms    #-}+{-# LANGUAGE PolyKinds          #-}+{-# LANGUAGE RankNTypes         #-}+{-# LANGUAGE TypeOperators      #-}+{-# LANGUAGE TypeFamilies       #-}+{-# LANGUAGE ViewPatterns       #-}++{-# OPTIONS_HADDOCK show-extensions #-}++#if __GLASGOW_HASKELL__ <= 802+-- ghc802 does not infer that 'cons' is used when using a bidirectional+-- pattern+{-# OPTIONS_GHC -Wno-unused-top-binds    #-}+-- the 'complete' pragma was introduced in ghc804+{-# OPTIONS_GHC -Wno-incomplete-patterns #-}+#endif+ module Control.Category.Free     ( -- * Free category-      Cat (..)+      Cat (Id)+    , arrCat+    , mapCat+    , foldCat       -- * Free category (CPS style)     , C (..)     , toC     , fromC+      -- * Oposite category+    , Op (..)        -- * Free interface re-exports     , FreeAlgebra2 (..)@@ -18,7 +42,7 @@     )     where -import           Prelude hiding (id, (.))+import           Prelude hiding (id, concat, (.)) import           Control.Category (Category (..)) import           Control.Algebra.Free2   ( AlgebraType0@@ -38,71 +62,115 @@ import           Data.Semigroup (Semigroup (..)) #endif --- |--- Free category encoded as a recursive data type, in a simlar way as--- @'Control.Monad.Free.Free'@.  You can use @'FreeAlgebra2'@ class instance:+import           Control.Category.Free.Internal ----- prop> liftFree2    @Cat :: f a b -> Cat f ab--- prop> foldNatFree2 @Cat :: Category d => (forall x y. f x y -> d x y) -> Cat f a b -> d a b+-- Free categories based on real time queues; Ideas after E.Kmett's guanxi+-- project. ----- The same performance concerns that apply to @'Control.Monad.Free.Free'@--- apply to this encoding of a free category.-data Cat :: (k -> k -> *) -> k -> k -> * where-  Id    :: Cat f a a-  (:.:) :: f b c -> Cat f a b -> Cat f a c -instance Category (Cat f) where-  id = Id-  Id         . ys = ys-  (x :.: xs) . ys = x :.: (xs . ys)--infixr 9 :.:+-- | Efficient encoding of a category for which morphism composition has+-- @O\(1\)@ complexity and fold is linear in the number of transitions.+-- +data Cat (f :: k -> k -> *) a b where+    Id   :: Cat f a a +    Cat  :: forall f a b c.+            f b c+         -> Queue (Cat f) a b+         -> Cat f a c  -instance Arrow f => Arrow (Cat f) where-  arr ab                          = arr ab :.: Id+-- | Smart constructor for embeding spanning transitions into 'Cat', the same+-- as @'liftFree2' \@'Cat'@.  It is like 'arr' for 'Arrows'.+--+arrCat :: forall (f :: k -> k -> *) a b.+         f a b+      -> Cat f a b+arrCat fab = Cat fab emptyQ -  Id *** Id                       = Id-  Id *** (fxb :.: cax)            = (arr id *** fxb) :.: (Id *** cax)-  (fxb :.: cax) *** Id            = (fxb *** arr id) :.: (cax *** Id)-  (fxb :.: cax) *** (fyb :.: cay) = (fxb *** fyb) :.: (cax *** cay)+-- | Smart constructor 'mapCat' for morphisms of @'Cat' f@ category.+--+mapCat :: forall (f :: k -> k -> *) a b c.+           f b c+        -> Cat f a b+        -> Cat f a c+mapCat fbc cab = arrCat fbc . cab -instance ArrowZero f => ArrowZero (Cat f) where-  zeroArrow = zeroArrow :.: Id+-- | Right fold of 'Cat' into a category, the same as @'foldNatFree2' \@'Cat'@.+--+-- /complexity/: @O\(n\) where @n@ is number of transition embedded in 'Cat'.+foldCat :: forall f c a b.+           Category c+        => (forall x y. f x y -> c x y)+        -> Cat f a b+        -> c a b+foldCat _nat Id = id+foldCat nat (Cat tr queue) =+    case queue of+      NilQ            -> nat tr+      ConsQ Id queue' -> nat tr . foldQ (foldCat nat) queue'+      ConsQ c  queue' -> nat tr . foldCat nat c . foldQ (foldCat nat) queue' -instance ArrowChoice f => ArrowChoice (Cat f) where-  Id +++ Id                       = Id-  Id +++ (fxb :.: cax)            = (arr id +++ fxb) :.: (Id +++ cax)-  (fxb :.: cax) +++ Id            = (fxb +++ arr id) :.: (cax +++ Id)-  (fxb :.: cax) +++ (fyb :.: cay) = (fxb +++ fyb) :.: (cax +++ cay)+-- TODO: implement foldl; it might require different representation.  Function+-- composition is applied from right to left, so it should be more efficient. -instance Semigroup (Cat f o o) where-  f <> g = g . f+-- | /complexity/ of composition @('.')@: @O\(1\)@ (worst case)+instance Category (Cat f) where+    id = Id -instance Monoid (Cat f o o) where-  mempty = Id-#if __GLASGOW_HASKELL__ < 804-  mappend = (<>)-#endif+    Id . f  = f+    f  . Id = f+    Cat f q . h = Cat f (q `snoc` h)  type instance AlgebraType0 Cat f = () type instance AlgebraType  Cat c = Category c +-- | /complexity/ of 'foldNatFree2': @O\(n\)@ where @n@ is number of+-- transitions embeded in 'Cat'.+-- instance FreeAlgebra2 Cat where-  liftFree2 = \fab -> fab :.: Id+  liftFree2 = arrCat   {-# INLINE liftFree2 #-} -  foldNatFree2 _   Id          = id-  foldNatFree2 fun (bc :.: ab) = fun bc . foldNatFree2 fun ab+  foldNatFree2 = foldCat   {-# INLINE foldNatFree2 #-}    codom2  = proof   forget2 = proof +instance Arrow f => Arrow (Cat f) where+    arr = arrCat . arr+    Cat tr queue *** Cat tr' queue' = Cat (tr *** tr') (zipWithQ (***) queue queue')+    Cat tr queue *** Id             = Cat (tr *** arr id) (zipWithQ (***) queue NilQ)+    Id           *** Cat tr' queue' = Cat (arr id *** tr') (zipWithQ (***) NilQ queue')+    Id           *** Id             = Cat (arr id *** arr id) NilQ++instance ArrowZero f => ArrowZero (Cat f) where+    zeroArrow = arrCat zeroArrow++instance ArrowChoice f => ArrowChoice (Cat f) where+    Cat fxb cax +++ Cat fyb cay+                         = Cat (fxb +++ fyb) (zipWithQ (+++) cax cay)+    Cat fxb cax +++ Id   = Cat (fxb +++ arr id) (zipWithQ (+++) cax NilQ)+    Id +++ (Cat fxb cax) = Cat (arr id +++ fxb) (zipWithQ (+++) NilQ cax)+    Id +++ Id            = Id++instance Semigroup (Cat f o o) where+    f <> g = f . g++instance Monoid (Cat f o o) where+    mempty = Id+#if __GLASGOW_HASKELL__ < 804+    mappend = (<>)+#endif++--+-- CPS style free categories+--+ -- | -- CPS style encoded free category; one can use @'FreeAlgebra2'@ class -- instance: ----- prop> liftFree2    @C :: f a b -> C f ab+-- prop> liftFree2    @C :: f a b -> C f a b -- prop> foldNatFree2 @C :: Category d => (forall x y. f x y -> d x y) -> C f a b -> d a b newtype C f a b   = C { runC :: forall r. Category r@@ -117,13 +185,13 @@ -- | -- Isomorphism from @'Cat'@ to @'C'@, which is a specialisation of -- @'hoistFreeH2'@.-toC :: Cat f a b -> C f a b+toC :: ListTr f a b -> C f a b toC = hoistFreeH2 {-# INLINE toC #-}  -- | -- Inverse of @'fromC'@, which also is a specialisatin of @'hoistFreeH2'@.-fromC :: C f a b -> Cat f a b+fromC :: C f a b -> ListTr f a b fromC = hoistFreeH2 {-# INLINE fromC #-} 
+ src/Control/Category/Free/Internal.hs view
@@ -0,0 +1,222 @@+{-# LANGUAGE CPP               #-}+{-# LANGUAGE GADTs             #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE PatternSynonyms   #-}+{-# LANGUAGE PolyKinds         #-}+{-# LANGUAGE RankNTypes        #-}+{-# LANGUAGE TypeFamilies      #-}+{-# LANGUAGE ViewPatterns      #-}++{-# OPTIONS_HADDOCK show-extensions #-}++#if __GLASGOW_HASKELL__ <= 802+-- ghc802 does not infer that 'cons' is used when using a bidirectional+-- pattern+{-# OPTIONS_GHC -Wno-unused-top-binds    #-}+-- the 'complete' pragma was introduced in ghc804+{-# OPTIONS_GHC -Wno-incomplete-patterns #-}+#endif+++-- | Internal module, contains implementation of type aligned real time queues+-- (C.Okasaki 'Purely Functional Data Structures').+--+module Control.Category.Free.Internal+  ( Op (..)+  , ListTr (..)+  , Queue (NilQ, ConsQ)+  , emptyQ+  , cons+  , uncons+  , snoc+  , foldQ+  , zipWithQ+  ) where+++import           Prelude hiding (id, (.))+import           Control.Arrow+import           Control.Category (Category (..))+#if __GLASGOW_HASKELL__ < 804+import           Data.Monoid (Monoid (..))+import           Data.Semigroup (Semigroup (..))+#endif++import           Control.Algebra.Free2 ( AlgebraType0+                                       , AlgebraType+                                       , FreeAlgebra2 (..)+                                       , proof+                                       )++-- | Oposite categoy in which arrows from @a@ to @b@ are represented by arrows+-- from @b@ to @a@ in the original category.+--+newtype Op (f :: k -> k -> *) (a :: k) (b :: k) = Op { runOp :: f b a }++instance Category f => Category (Op f) where+    id = Op id+    Op f . Op g = Op (g . f)++instance Category f => Semigroup (Op f o o) where+    (<>) = (.)++instance Category f => Monoid (Op f o o) where+    mempty = id+#if __GLASGOW_HASKELL__ < 804+    mappend = (<>)+#endif++-- |+-- Free category encoded as a recursive data type, in a simlar way as+-- @'Control.Monad.Free.Free'@.  You can use @'FreeAlgebra2'@ class instance:+--+-- prop> liftFree2    @Cat :: f a b -> Cat f ab+-- prop> foldNatFree2 @Cat :: Category d => (forall x y. f x y -> d x y) -> Cat f a b -> d a b+--+-- The same performance concerns that apply to @'Control.Monad.Free.Free'@+-- apply to this encoding of a free category.+--+data ListTr :: (k -> k -> *) -> k -> k -> * where+  NilTr  :: ListTr f a a+  ConsTr :: f b c -> ListTr f a b -> ListTr f a c++instance Category (ListTr f) where+  id = NilTr+  NilTr    . ys = ys+  (ConsTr x xs) . ys = ConsTr x (xs . ys)++instance Arrow f => Arrow (ListTr f) where+  arr ab                          = arr ab `ConsTr` NilTr++  (ConsTr fxb cax) *** (ConsTr fyb cay)+                             = (fxb *** fyb)    `ConsTr` (cax *** cay)+  (ConsTr fxb cax) *** NilTr = (fxb *** arr id) `ConsTr` (cax *** NilTr)+  NilTr *** (ConsTr fxb cax) = (arr id *** fxb) `ConsTr` (NilTr *** cax)+  NilTr *** NilTr            = NilTr++instance ArrowZero f => ArrowZero (ListTr f) where+  zeroArrow = zeroArrow `ConsTr` NilTr++instance ArrowChoice f => ArrowChoice (ListTr f) where+  (ConsTr fxb cax) +++ (ConsTr fyb cay)+                             = (fxb +++ fyb)    `ConsTr` (cax +++ cay)+  (ConsTr fxb cax) +++ NilTr = (fxb +++ arr id) `ConsTr` (cax +++ NilTr)+  NilTr +++ (ConsTr fxb cax) = (arr id +++ fxb) `ConsTr` (NilTr +++ cax)+  NilTr +++ NilTr            = NilTr++instance Semigroup (ListTr f o o) where+  f <> g = g . f++instance Monoid (ListTr f o o) where+  mempty = NilTr+#if __GLASGOW_HASKELL__ < 804+  mappend = (<>)+#endif++type instance AlgebraType0 ListTr f = ()+type instance AlgebraType  ListTr c = Category c++instance FreeAlgebra2 ListTr where+  liftFree2 = \fab -> ConsTr fab NilTr+  {-# INLINE liftFree2 #-}++  foldNatFree2 _   NilTr     = id+  foldNatFree2 fun (ConsTr bc ab) = fun bc . foldNatFree2 fun ab+  {-# INLINE foldNatFree2 #-}++  codom2  = proof+  forget2 = proof+++-- | Type alligned real time queues; Based on `Purely Functinal Data Structures`+-- C.Okasaki.+--+-- Upper bounds of `cons`, `snoc`, `uncons` are @O\(1\)@ (worst case).+--+-- Invariant: sum of lengths of two last least is equal the length of the first+-- one.+--+data Queue (f :: k -> k -> *) (a :: k) (b :: k) where+    Queue :: forall f a c b x.+             !(ListTr f b c)+          -> !(ListTr (Op f) b a)+          -> !(ListTr f b x)+          -> Queue f a c++emptyQ :: Queue (f :: k -> k -> *) a a+emptyQ = Queue NilTr NilTr NilTr++cons :: forall (f :: k -> k -> *) a b c.+        f b c+     -> Queue f a b+     -> Queue f a c+cons fbc (Queue f r s) = Queue (ConsTr fbc f) r (ConsTr undefined s)++data ViewL f a b where+    EmptyL :: ViewL f a a+    (:<)   :: f b c -> Queue f a b -> ViewL f a c++-- | 'uncons' a 'Queue', complexity: @O\(1\)@+--+uncons :: Queue f a b+       -> ViewL f a b+uncons (Queue NilTr NilTr _)                = EmptyL+uncons (Queue (ConsTr tr f) r (ConsTr _ s)) = tr :< exec f r s+uncons _                                    = error "Queue.uncons: invariant violation"++snoc :: forall (f :: k -> k -> *) a b c.+        Queue f b c+     -> f a b+     -> Queue f a c+snoc (Queue f r s) g = exec f (ConsTr (Op g) r) s++pattern ConsQ :: f b c -> Queue f a b -> Queue f a c+pattern ConsQ a as <- (uncons -> a :< as) where+    ConsQ = cons++pattern NilQ :: () => a ~ b => Queue f a b+pattern NilQ <- (uncons -> EmptyL) where+    NilQ = emptyQ++#if __GLASGOW_HASKELL__ > 802+{-# complete NilQ, ConsQ #-}+#endif++-- | Efficient fold of a queue into a category.+--+-- /complexity/ @O\(n\)@+--+foldQ :: forall (f :: k -> k -> *) c a b.+         Category c+      => (forall x y. f x y -> c x y)+      -> Queue f a b+      -> c a b+foldQ nat queue = case queue of+    NilQ            -> id+    ConsQ tr queue' -> nat tr . foldQ nat queue'++zipWithQ :: forall f g a b a' b'.+        Arrow f+     => (forall x y x' y'. f x y -> f x' y' -> f (g x x') (g y y'))+     -> Queue f a  b+     -> Queue f a' b'+     -> Queue f (g a a') (g b b')+zipWithQ fn queueA queueB = case (queueA, queueB) of+    (NilQ, NilQ) -> NilQ+    (NilQ, ConsQ trB' queueB') -> ConsQ (id   `fn` trB') (zipWithQ fn NilQ    queueB')+    (ConsQ trA' queueA', NilQ) -> ConsQ (trA' `fn` id)   (zipWithQ fn queueA' NilQ)+    (ConsQ trA' queueA', ConsQ trB' queueB')+                               -> ConsQ (trA' `fn` trB') (zipWithQ fn queueA' queueB')++++exec :: ListTr f b c -> ListTr (Op f) b a -> ListTr f b x -> Queue f a c+exec xs ys (ConsTr _ t) = Queue xs ys t+exec xs ys NilTr        = Queue xs' NilTr xs'+  where+    xs' = rotate xs ys NilTr++rotate :: ListTr f c d -> ListTr (Op f) c b -> ListTr f a b -> ListTr f a d+rotate NilTr         (ConsTr (Op f) NilTr) a = ConsTr f a+rotate (ConsTr f fs) (ConsTr (Op g) gs)    a = ConsTr f (rotate fs gs (ConsTr g a))+rotate _             _                     _ = error "Queue.rotate: impossible happend"
src/Control/Category/FreeEff.hs view
@@ -1,4 +1,12 @@+{-# LANGUAGE GADTs                  #-}+{-# LANGUAGE FlexibleInstances      #-} {-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE PolyKinds              #-}+{-# LANGUAGE RankNTypes             #-}+{-# LANGUAGE TypeFamilies           #-}++{-# OPTIONS_HADDOCK show-extensions #-}+ module Control.Category.FreeEff   ( EffCategory (..)   , FreeEffCat (..)@@ -13,7 +21,7 @@ import Control.Category (Category (..)) import Data.Functor.Identity (Identity (..)) -import Control.Category.Free (Cat (..))+import Control.Category.Free (Cat) import Control.Algebra.Free2 (FreeAlgebra2 (..)) import Data.Algebra.Free (AlgebraType, AlgebraType0, proof)