packages feed

day-comonoid (empty) → 0.1

raw patch · 5 files changed

+271/−0 lines, 5 filesdep +basedep +comonaddep +kan-extensions

Dependencies added: base, comonad, kan-extensions

Files

+ CHANGELOG.md view
@@ -0,0 +1,5 @@+# Revision history for day-comonoid++## 0.1 -- 2023-10-15++* First version.
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2023, Koji Miyazato++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 Koji Miyazato 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,55 @@+# day-comonid: The(?) dual of Applicative++This package provides a type class named `Comonoid`.++```haskell+class Comonad f => Comonoid f where+    coapply :: f a -> Day f f a+```++The name "Comonoid" should be read in a context. A functor `f` being `Comonoid` means it's a comonoid in the category of `Functor`s+equipped with [Day](https://hackage.haskell.org/package/kan-extensions-5.2.5/docs/Data-Functor-Day.html) as its tensor product.++`Comonoid` can be contrasted with `Applicative`, which is equivalent to a type class for monoids in the said category of `Functor`s.++```haskell+class Functor f => Applicative f where+    pure  :: a -> f a+    (<*>) :: f (a -> b) -> f a -> f b++-- A hypothetical type class equivalent to Applicative+class Functor f => DayMonoid f where+    pure' :: Identity a -> f a+    default pure' :: Applicative f => Identity a -> f a+    pure' = pure . runIdentity++    ap' :: Day f f a -> f a+    default ap' :: Applicative f => Day f f a -> f a+    ap' = dap+```++`Comonoid` is related to [Comonad](https://hackage.haskell.org/package/comonad-5.0.8/docs/Control-Comonad.html),+just like `Applicative` is related to `Monad`.++`Applicative` is a superclass of `Monad` *just because*+any `Monad f` instance is sufficient to implement `Applicative f` in a certain way.++Similarly, `Comonad` is a superclass of `Comonoid`,+*just because* having `(extract :: f a -> a)` and `coapply` is sufficient to make `f` a `Comonad`.++| `Applicative` | `=>` | `Monad` |+|----|----|----|+| `a -> f a`    |      | `a -> f a` |+| `Day f f a -> f a` |  | `f (f a) -> f a` |++| `Comonoid` | `<=` | `Comonad` |+|----|----|----|+| `f a -> a`    |      | `f a -> a` |+| `f a -> Day f f a` |  | `f a -> f (f a)` |++Both of these relations are rooted in the same fact that the following conversion is possible for any `Functor f` and `Functor g`:++```haskell+dayToCompose :: (Functor f, Functor g) => Day f g a -> f (g a)+dayToCompose (Day fb fc op) = fmap (\b -> fmap (op b) fc) fb+```
+ day-comonoid.cabal view
@@ -0,0 +1,33 @@+cabal-version:      2.2+name:               day-comonoid+version:            0.1+synopsis:           A comonoid w.r.t. Day+description:+  A type class Comonoid to represend a comonoid w.r.t. Day,+  just like Applicative is a type class of monoid w.r.t. Day.++  See README.md for more information.+license:            BSD-3-Clause+license-file:       LICENSE+homepage:           https://github.com/viercc/functor-monad/tree/main/day-comonoid+author:             Koji Miyazato+maintainer:         viercc@gmail.com+copyright:          Koji Miyazato+category:           Data Structures, Comonads, Functors+build-type:         Simple+extra-doc-files:    CHANGELOG.md+extra-source-files: README.md++common warnings+    ghc-options: -Wall -Wcompat++library+    import:           warnings+    exposed-modules:+        Data.Functor.Day.Comonoid+    build-depends:+        base >= 4.10 && < 5,+        kan-extensions >= 5 && < 5.3,+        comonad >= 5.0.8 && < 5.1+    hs-source-dirs:   src+    default-language: Haskell2010
+ src/Data/Functor/Day/Comonoid.hs view
@@ -0,0 +1,148 @@+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE InstanceSigs #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-}++module Data.Functor.Day.Comonoid (+  -- * Comonoid type class+  Comonoid (..), erase1, erase2, duplicateDefault, extendDefault, dayToCompose,+  -- * Re-export+  Comonad(..)+  ) where++import Data.Functor.Day+import Data.Functor.Sum ( Sum(..) )+import Data.Functor.Identity (Identity(..))++import Control.Comonad (Comonad(..))+import Control.Comonad.Trans.Identity (IdentityT(..))+import Control.Comonad.Env (EnvT(..) )+import Control.Comonad.Traced (TracedT(..) )++-- | Comonoid with respect to Day convolution.+--+-- ==== Laws+-- +-- 'coapply' must satisfy the following equations. Here, @erase1@ and @erase2@+-- are defined using 'extract' method inherited from 'Comonad'.+-- +-- @+-- 'erase1' . 'coapply' = id+-- 'erase2' . 'coapply' = id+-- 'trans1' 'coapply' . 'coapply' = 'assoc' . 'trans2' 'coapply' . 'coapply'+-- @+-- +-- Furthermore, 'duplicateDefault' derived from @coapply@ must be equivalent to 'duplicate'+-- inherited from 'Comonad'.+-- +-- @+-- 'duplicateDefault' = 'dayToCompose' . coapply+--                  = 'duplicate'+-- @+--+-- ==== Examples+-- +-- Env comonad, or @(,) e@, is an instance of @Comonoid@.+--+-- +-- > instance Comonoid ((,) e) where+-- >   coapply :: forall x. (e, x) -> Day ((,) e) ((,) e) x+-- >   -- ~ forall x. (e,x) -> ∃b c. ((e,b), (e,c), b -> c -> x)+-- >   -- ~ forall x. (e,x) -> (e,e, ∃b c.(b, c, b -> c -> x))+-- >   -- ~ forall x. (e,x) -> (e,e,x)+-- >   -- ~ e -> (e,e)+-- >   coapply (e, x) = Day (e, ()) (e, ()) (\_ _ -> x)+--+-- Traced comonad, or @((->) m)@, is another example.+-- +-- > instance Monoid m => Comonoid ((->) m) where+-- >   coapply :: forall x. (m -> x) -> Day ((->) m) ((->) m) x+-- >   -- ~ forall x. (m -> x) -> ∃b c. (m -> b, m -> c, b -> c -> x)+-- >   -- ~ forall x. (m -> x) -> (m -> m -> x)+-- >   -- ~ m -> m -> m+-- >   coapply f = Day id id (\x y -> f (x <> y))+--+-- ==== Non-example+--+-- Unlike @Env@ or @Traced@, 'Control.Comonad.Store.Store' comonad can't be an instance of @Comonoid@.+-- The law requires any lawful @Comonoid f@ to satisfy the following property.+-- +-- * For any value of @f x@, 'coapply' doesn't change the \"shape\" of it. Precisely, for any value @fx :: f x@,+--   the following equation is true.+--+--     > () <$ coapply fx ≡ Day (() <$ fx) (() <$ fx) (\_ _ -> ())@+-- +-- Therefore, any lawful @Comonoid (Store s)@ must satisfy the following equation:+--+-- > coapply (store u s0) ≡ Day (store u s0) (store u s0) (\_ _ -> ())+-- >   where u = const () :: s -> ()+-- +-- But it's incompatible with another requirement that @duplicateDefault@ must be equivalent to @duplicate@ of+-- the @Comonad (Store s)@ instance.+--+-- > duplicateDefault (store u s0) = store (const (store u s0)) s0+-- > duplicate        (store u s0) = store (\s1 -> store u s1)  s0++class Comonad f => Comonoid f where+  coapply :: f a -> Day f f a++-- | Every 'Comonoid' is a 'Comonad'.+duplicateDefault :: Comonoid f => f a -> f (f a)+duplicateDefault = dayToCompose . coapply++-- | Every 'Comonoid' is a 'Comonad'.+extendDefault :: Comonoid f => (f a -> b) -> f a -> f b+extendDefault t = fmap t . duplicateDefault+++-- | @'Day' f g@ can be turned into a composition of @f@ and @g@.+dayToCompose :: (Functor f, Functor g) => Day f g a -> f (g a)+dayToCompose (Day fb fc op) = fmap (\b -> fmap (op b) fc) fb++-- | @erase1 = elim1 . trans1 (Identity . extract)@+erase1 :: (Comonad f, Functor g) => Day f g c -> g c+erase1 fg = case fg of+  Day f g op -> op (extract f) <$> g++-- | @erase2 = elim2 . trans2 (Identity . extract)@+erase2 :: (Functor f, Comonad g) => Day f g c -> f c+erase2 fg = case fg of+  Day f g op -> (\a -> op a (extract g)) <$> f++-- | @transBi t u = trans1 t . trans2 u = trans2 u . trans1 t@+transBi :: (forall x. f x -> f' x) -> (forall x. g x -> g' x) -> Day f g a -> Day f' g' a+transBi t u (Day f g op) = Day (t f) (u g) op++interchange :: Day (Day f f') (Day g g') x -> Day (Day f g) (Day f' g') x+-- interchange = disassoc . trans1 (assoc . trans2 swapped . disassoc) . assoc+interchange (Day (Day fa fb ab_x) (Day gc gd cd_y) xy_r) =+  Day (Day fa gc (,)) (Day fb gd (,)) (\(a,c) (b,d) -> xy_r (ab_x a b) (cd_y c d))++instance Comonoid Identity where+  coapply (Identity a) = Day (Identity ()) (Identity ()) (\_ _ -> a)++instance Comonoid ((,) e) where+  coapply :: forall x. (e, x) -> Day ((,) e) ((,) e) x+  coapply (e, x) = Day (e, ()) (e, ()) (\_ _ -> x)++instance Monoid m => Comonoid ((->) m) where+  coapply :: forall x. (m -> x) -> Day ((->) m) ((->) m) x+  coapply f = Day id id (\x y -> f (x <> y))++instance (Comonoid f, Comonoid g) => Comonoid (Sum f g) where+  coapply (InL f) = transBi InL InL (coapply f)+  coapply (InR g) = transBi InR InR (coapply g)++instance (Comonoid f, Comonoid g) => Comonoid (Day f g) where+  coapply = interchange . transBi coapply coapply++instance (Comonoid f) => Comonoid (IdentityT f) where+  coapply (IdentityT fx) = transBi IdentityT IdentityT (coapply fx)++instance (Comonoid f) => Comonoid (EnvT e f) where+  coapply (EnvT e fx) = transBi (EnvT e) (EnvT e) (coapply fx)++instance (Monoid m, Comonoid f) => Comonoid (TracedT m f) where+  coapply (TracedT ft) = case coapply ft of+    Day fa fb op -> Day (TracedT ((,) <$> fa)) (TracedT ((,) <$> fb)) (\(a, m1) (b, m2) -> op a b (m1 <> m2))