packages feed

free-categories (empty) → 0.1.0.0

raw patch · 6 files changed

+328/−0 lines, 6 filesdep +basesetup-changed

Dependencies added: base

Files

+ CHANGELOG.md view
@@ -0,0 +1,5 @@+# Revision history for free-categories++## 0.1.0.0 -- 2019-10-01++* First version.
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2019, Eitan Chatav++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Eitan Chatav nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,31 @@+# free-categories++Consider the category of Haskell "quivers" with++* objects are types of higher kind+  * `p :: k -> k -> Type`+* morphisms are terms of `RankNType`,+  * `forall x y. p x y -> q x y`+* identity is `id`+* composition is `.`++Now, consider the subcategory of Haskell `Category`s with++* constrained objects `Category c => c`+* morphisms act functorially+  * `t :: (Category c, Category d) => c x y -> d x y`+  * `t id = id`+  * `t (g . f) = t g . t f`++The [free category functor](https://ncatlab.org/nlab/show/free+category)+from quivers to `Category`s may be defined up to isomorphism as++* the functor `Path` of type-aligned lists++* the functor `FoldPath` of categorical folds++* abstractly as `CFree path => path`, the class of+  left adjoints to the functor which+  forgets the constraint on `Category c => c`++* or as any isomorphic data structure
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ free-categories.cabal view
@@ -0,0 +1,21 @@+cabal-version:       >=1.10++name:                free-categories+version:             0.1.0.0+synopsis:            free categories+description:         free categories, paths, and categorical folds+homepage:            http://github.com/morphismtech/free-categories+bug-reports:         http://github.com/morphismtech/free-categories/issues+license:             BSD3+license-file:        LICENSE+author:              Eitan Chatav+maintainer:          eitan@morphism.tech+category:            Control+build-type:          Simple+extra-source-files:  CHANGELOG.md, README.md++library+  exposed-modules:     Control.Category.Free+  build-depends:       base >=4.12 && <=5+  hs-source-dirs:      src+  default-language:    Haskell2010
+ src/Control/Category/Free.hs view
@@ -0,0 +1,239 @@+{-|+Module: Control.Category.Free+Description: free categories+Copyright: (c) Eitan Chatav, 2019+Maintainer: eitan@morphism.tech+Stability: experimental++Consider the category of Haskell "quivers" with++* objects are types of higher kind+  * @p :: k -> k -> Type@+* morphisms are terms of @RankNType@,+  * @forall x y. p x y -> q x y@+* identity is `id`+* composition is `.`++Now, consider the subcategory of Haskell `Category`s with++* constrained objects `Category` @c => c@+* morphisms act functorially+  * @t :: (Category c, Category d) => c x y -> d x y@+  * @t id = id@+  * @t (g . f) = t g . t f@++The [free category functor](https://ncatlab.org/nlab/show/free+category)+from quivers to `Category`s may be defined up to isomorphism as++* the functor `Path` of type-aligned lists++* the functor `FoldPath` of categorical folds++* abstractly as `CFree` @path => path@, the class of+  left adjoints to the functor which+  forgets the constraint on `Category` @c => c@++* or as any isomorphic data structure+-}++{-# LANGUAGE+    FlexibleInstances+  , GADTs+  , LambdaCase+  , MultiParamTypeClasses+  , PatternSynonyms+  , PolyKinds+  , QuantifiedConstraints+  , RankNTypes+  , StandaloneDeriving+#-}++module Control.Category.Free+  ( Path (..)+  , pattern (:<<)+  , FoldPath (..)+  , Category (..)+  , CFunctor (..)+  , CFoldable (..)+  , CTraversable (..)+  , CFree (..)+  , toPath+  , EndoL (..)+  , EndoR (..)+  , MCat (..)+  , ApCat (..)+  ) where++import Control.Category+import Prelude hiding (id, (.))++{- | A `Path` with steps in @p@ is a singly linked list of+"type-aligned" constructions of @p@.++>>> :{+let+  path :: Path (->) String Int+  path = length :>> (\x -> x^2) :>> Done+in+  cfold path "hello"+:}+25+-}+data Path p x y where+  Done :: Path p x x+  (:>>) :: p x y -> Path p y z -> Path p x z+infixr 7 :>>+{- | The snoc pattern for right-to-left composition.-}+pattern (:<<) :: Path p y z -> p x y -> Path p x z+pattern ps :<< p = p :>> ps+infixl 7 :<<+deriving instance (forall x y. Show (p x y)) => Show (Path p x y)+instance x ~ y => Semigroup (Path p x y) where+  (<>) = (>>>)+instance x ~ y => Monoid (Path p x y) where+  mempty = Done+  mappend = (>>>)+instance Category (Path p) where+  id = Done+  (.) path = \case+    Done -> path+    p :>> ps -> p :>> (ps >>> path)+instance CFunctor Path where+  cmap _ Done = Done+  cmap f (p :>> ps) = f p :>> cmap f ps+instance CFoldable Path where+  cfoldMap _ Done = id+  cfoldMap f (p :>> ps) = f p >>> cfoldMap f ps+  ctoMonoid _ Done = mempty+  ctoMonoid f (p :>> ps) = f p <> ctoMonoid f ps+  ctoList _ Done = []+  ctoList f (p :>> ps) = f p : ctoList f ps+  ctraverse_ _ Done = pure id+  ctraverse_ f (p :>> ps) = (>>>) <$> f p <*> ctraverse_ f ps+instance CTraversable Path where+  ctraverse _ Done = pure Done+  ctraverse f (p :>> ps) = (:>>) <$> f p <*> ctraverse f ps+instance CFree Path where csingleton p = p :>> Done++{- | Encodes a path as its `cfoldMap` function.-}+newtype FoldPath p x y = FoldPath+  {getFoldPath :: forall q. Category q => (forall x y. p x y -> q x y) -> q x y}+instance x ~ y => Semigroup (FoldPath p x y) where+  (<>) = (>>>)+instance x ~ y => Monoid (FoldPath p x y) where+  mempty = id+  mappend = (>>>)+instance Category (FoldPath p) where+  id = FoldPath $ \ _ -> id+  FoldPath g . FoldPath f = FoldPath $ \ k -> g k . f k+instance CFunctor FoldPath where cmap f = cfoldMap (csingleton . f)+instance CFoldable FoldPath where cfoldMap k (FoldPath f) = f k+instance CTraversable FoldPath where+  ctraverse f = getApCat . cfoldMap (ApCat . fmap csingleton . f)+instance CFree FoldPath where csingleton p = FoldPath $ \ k -> k p++{- | A functor from quivers to `Category`s.++prop> cmap _ id = id+prop> cmap f (c >>> c') = f c >>> f c'+-}+class (forall p. Category (c p)) => CFunctor c where+  cmap :: (forall x y. p x y -> q x y) -> c p x y -> c q x y++{- | Generalizing `Foldable` from `Monoid`s to `Category`s.++prop> cmap f = cfoldMap (csingleton . f)+-}+class CFunctor c => CFoldable c where+  {- | Map each element of the structure to a `Category`,+  and combine the results.-}+  cfoldMap :: Category q => (forall x y. p x y -> q x y) -> c p x y -> q x y+  {- | Combine the elements of a structure using a `Category`.-}+  cfold :: Category q => c q x y -> q x y+  cfold = cfoldMap id+  {- | Right-associative fold of a structure.++  In the case of `Path`s, `cfoldr`, when applied to a binary operator,+  a starting value, and a `Path`, reduces the `Path` using the binary operator,+  from right to left:++  prop> cfoldr (?) q (p1 :>> p2 :>> ... :>> pn :>> Done) == p1 ? (p2 ? ... (pn ? q) ...)+  -}+  cfoldr :: (forall x y z . p x y -> q y z -> q x z) -> q y z -> c p x y -> q x z+  cfoldr (?) q c = getEndoR (cfoldMap (\ x -> EndoR (\ y -> x ? y)) c) q+  {- | Left-associative fold of a structure.++  In the case of `Path`s, `cfoldl`, when applied to a binary operator,+  a starting value, and a `Path`, reduces the `Path` using the binary operator,+  from left to right:++  prop> cfoldl (?) q (p1 :>> p2 :>> ... :>> pn :>> Done) == (... ((q ? p1) ? p2) ? ...) ? pn+  -}+  cfoldl :: (forall x y z . q x y -> p y z -> q x z) -> q x y -> c p y z -> q x z+  cfoldl (?) q c = getEndoL (cfoldMap (\ x -> EndoL (\ y -> y ? x)) c) q+  {- | Map each element of the structure to a `Monoid`,+  and combine the results.-}+  ctoMonoid :: Monoid m => (forall x y. p x y -> m) -> c p x y -> m+  ctoMonoid f = getMCat . cfoldMap (MCat . f)+  {- | Map each element of the structure, and combine the results in a list.-}+  ctoList :: (forall x y. p x y -> a) -> c p x y -> [a]+  ctoList f = ctoMonoid (pure . f)+  {- | Map each element of a structure to an `Applicative` on a `Category`,+  evaluate from left to right, and combine the results.-}+  ctraverse_+    :: (Applicative m, Category q)+    => (forall x y. p x y -> m (q x y)) -> c p x y -> m (q x y)+  ctraverse_ f = getApCat . cfoldMap (ApCat . f)++{- | Generalizing `Traversable` to `Category`s.-}+class CFoldable c => CTraversable c where+  {- | Map each element of a structure to an `Applicative` on a quiver,+  evaluate from left to right, and collect the results.-}+  ctraverse+    :: Applicative m+    => (forall x y. p x y -> m (q x y)) -> c p x y -> m (c q x y)++{- | Unpacking the definition of a left adjoint to the forgetful functor+from `Category`s to quivers, there must be a function `csingleton`,+such that any function++@f :: Category d => p x y -> d x y@++factors uniquely through @c p x y@ as++prop> cfoldMap f . csingleton = f+-}+class CTraversable c => CFree c where csingleton :: p x y -> c p x y++{- | `toPath` collapses any `CFoldable` into a `CFree`.+It is the unique isomorphism which exists+between any two `CFree` functors.+-}+toPath :: (CFoldable c, CFree path) => c p x y -> path p x y+toPath = cfoldMap csingleton++{- | Used in the default definition of `cfoldr`.-}+newtype EndoR p y x = EndoR {getEndoR :: forall z. p x z -> p y z}+instance Category (EndoR p) where+  id = EndoR id+  EndoR f1 . EndoR f2 = EndoR (f2 . f1)++{- | Used in the default definition of `cfoldr`.-}+newtype EndoL p x y = EndoL {getEndoL :: forall w . p w x -> p w y}+instance Category (EndoL p) where+  id = EndoL id+  EndoL f1 . EndoL f2 = EndoL (f1 . f2)++{- | Turn a `Monoid` into a `Category`,+used in the default definition of `ctoMonoid`.-}+newtype MCat m x y = MCat {getMCat :: m} deriving (Eq, Ord, Show)+instance Monoid m => Category (MCat m) where+  id = MCat mempty+  MCat g . MCat f = MCat (f <> g)++{- | Turn an `Applicative` over a `Category` into a `Category`,+used in the default definition of `ctraverse_`.-}+newtype ApCat m c x y = ApCat {getApCat :: m (c x y)} deriving (Eq, Ord, Show)+instance (Applicative m, Category c) => Category (ApCat m c) where+  id = ApCat (pure id)+  ApCat g . ApCat f = ApCat ((.) <$> g <*> f)