comonad 1.1.1.6 → 3.0
raw patch · 3 files changed
+215/−247 lines, 3 filesdep ~semigroupsPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: semigroups
API changes (from Hackage documentation)
- Control.Comonad: class Functor w => Extend w where extend f = fmap f . duplicate duplicate = extend id
- Control.Comonad: instance (Semigroup m, Monoid m) => Comonad ((->) m)
- Data.Functor.Extend: (<<=) :: Extend w => (w a -> b) -> w a -> w b
- Data.Functor.Extend: (=<=) :: Extend w => (w b -> c) -> (w a -> b) -> w a -> c
- Data.Functor.Extend: (=>=) :: Extend w => (w a -> b) -> (w b -> c) -> w a -> c
- Data.Functor.Extend: (=>>) :: Extend w => w a -> (w a -> b) -> w b
- Data.Functor.Extend: class Functor w => Extend w where extend f = fmap f . duplicate duplicate = extend id
- Data.Functor.Extend: duplicate :: Extend w => w a -> w (w a)
- Data.Functor.Extend: extend :: Extend w => (w a -> b) -> w a -> w b
- Data.Functor.Extend: instance Extend ((,) e)
- Data.Functor.Extend: instance Extend (Either a)
- Data.Functor.Extend: instance Extend Identity
- Data.Functor.Extend: instance Extend Maybe
- Data.Functor.Extend: instance Extend NonEmpty
- Data.Functor.Extend: instance Extend Seq
- Data.Functor.Extend: instance Extend Tree
- Data.Functor.Extend: instance Extend []
- Data.Functor.Extend: instance Extend w => Extend (IdentityT w)
- Data.Functor.Extend: instance Semigroup m => Extend ((->) m)
+ Control.Comonad: ($>) :: Functor f => f a -> b -> f b
+ Control.Comonad: (<$) :: Functor f => a -> f b -> f a
+ Control.Comonad: (<$>) :: Functor f => (a -> b) -> f a -> f b
+ Control.Comonad: (<@) :: ComonadApply w => w a -> w b -> w a
+ Control.Comonad: (<@>) :: ComonadApply w => w (a -> b) -> w a -> w b
+ Control.Comonad: (<@@>) :: ComonadApply w => w a -> w (a -> b) -> w b
+ Control.Comonad: (@>) :: ComonadApply w => w a -> w b -> w b
+ Control.Comonad: cfix :: Comonad w => (w a -> a) -> w a
+ Control.Comonad: class Comonad w => ComonadApply w where a @> b = const id <$> a <@> b a <@ b = const <$> a <@> b
+ Control.Comonad: class Functor (f :: * -> *)
+ Control.Comonad: fmap :: Functor f => (a -> b) -> f a -> f b
+ Control.Comonad: instance ComonadApply Identity
+ Control.Comonad: instance ComonadApply NonEmpty
+ Control.Comonad: instance ComonadApply Tree
+ Control.Comonad: instance ComonadApply w => ArrowLoop (Cokleisli w)
+ Control.Comonad: instance ComonadApply w => ComonadApply (IdentityT w)
+ Control.Comonad: instance Monoid m => Comonad ((->) m)
+ Control.Comonad: instance Monoid m => ComonadApply ((->) m)
+ Control.Comonad: instance Semigroup m => ComonadApply ((,) m)
+ Control.Comonad: liftW2 :: ComonadApply w => (a -> b -> c) -> w a -> w b -> w c
+ Control.Comonad: liftW3 :: ComonadApply w => (a -> b -> c -> d) -> w a -> w b -> w c -> w d
- Control.Comonad: (<<=) :: Extend w => (w a -> b) -> w a -> w b
+ Control.Comonad: (<<=) :: Comonad w => (w a -> b) -> w a -> w b
- Control.Comonad: (=<=) :: Extend w => (w b -> c) -> (w a -> b) -> w a -> c
+ Control.Comonad: (=<=) :: Comonad w => (w b -> c) -> (w a -> b) -> w a -> c
- Control.Comonad: (=>=) :: Extend w => (w a -> b) -> (w b -> c) -> w a -> c
+ Control.Comonad: (=>=) :: Comonad w => (w a -> b) -> (w b -> c) -> w a -> c
- Control.Comonad: (=>>) :: Extend w => w a -> (w a -> b) -> w b
+ Control.Comonad: (=>>) :: Comonad w => w a -> (w a -> b) -> w b
- Control.Comonad: class Extend w => Comonad w
+ Control.Comonad: class Functor w => Comonad w where duplicate = extend id extend f = fmap f . duplicate
- Control.Comonad: duplicate :: Extend w => w a -> w (w a)
+ Control.Comonad: duplicate :: Comonad w => w a -> w (w a)
- Control.Comonad: extend :: Extend w => (w a -> b) -> w a -> w b
+ Control.Comonad: extend :: Comonad w => (w a -> b) -> w a -> w b
Files
- Control/Comonad.hs +213/−94
- Data/Functor/Extend.hs +0/−150
- comonad.cabal +2/−3
Control/Comonad.hs view
@@ -2,7 +2,7 @@ ----------------------------------------------------------------------------- -- | -- Module : Control.Comonad--- Copyright : (C) 2008-2011 Edward Kmett,+-- Copyright : (C) 2008-2012 Edward Kmett, -- (C) 2004 Dave Menendez -- License : BSD-style (see the file LICENSE) --@@ -11,93 +11,254 @@ -- Portability : portable -- -----------------------------------------------------------------------------module Control.Comonad ( - -- * Extendable Functors- Extend(..)+module Control.Comonad (+ -- * Comonads+ Comonad(..)+ , liftW -- :: Comonad w => (a -> b) -> w a -> w b+ , wfix -- :: Comonad w => w (w a -> a) -> a+ , cfix -- :: Comonad w => (w a -> a) -> w a , (=>=) , (=<=) , (<<=) , (=>>)- -- * Comonads- -- $definition- , Comonad(..)- , liftW -- :: Comonad w => (a -> b) -> w a -> w b- , wfix -- :: Comonad w => w (w a -> a) -> a-+ -- * Combining Comonads+ , ComonadApply(..)+ , (<@@>) -- :: ComonadApply w => w a -> w (a -> b) -> w b+ , liftW2 -- :: ComonadApply w => (a -> b -> c) -> w a -> w b -> w c+ , liftW3 -- :: ComonadApply w => (a -> b -> c -> d) -> w a -> w b -> w c -> w d -- * Cokleisli Arrows , Cokleisli(..)+ -- * Functors+ , Functor(..)+ , (<$>) -- :: Functor f => (a -> b) -> f a -> f b+ , ($>) -- :: Functor f => f a -> b -> f b ) where -import Prelude hiding (id, (.))+-- import _everything_ import Control.Applicative import Control.Arrow import Control.Category+import Control.Monad (ap)+import Control.Monad.Instances import Control.Monad.Trans.Identity import Data.Functor.Identity-import Data.Functor.Extend-import Data.List.NonEmpty-import Data.Typeable-import Data.Semigroup+import Data.List.NonEmpty hiding (map)+import Data.Semigroup hiding (Product) import Data.Tree+import Prelude hiding (id, (.))+import Control.Monad.Fix+import Data.Typeable -{- | $definition -}+infixl 4 <@, @>, <@@>, <@>, $>+infixl 1 =>>+infixr 1 <<=, =<=, =>= -class Extend w => Comonad w where- -- | +{- |++There are two ways to define a comonad:++I. Provide definitions for 'extract' and 'extend'+satisfying these laws:++> extend extract = id+> extract . extend f = f+> extend f . extend g = extend (f . extend g)++In this case, you may simply set 'fmap' = 'liftW'.++These laws are directly analogous to the laws for monads+and perhaps can be made clearer by viewing them as laws stating+that Cokleisli composition must be associative, and has extract for+a unit:++> f =>= extract = f+> extract =>= f = f+> (f =>= g) =>= h = f =>= (g =>= h)++II. Alternately, you may choose to provide definitions for 'fmap',+'extract', and 'duplicate' satisfying these laws:++> extract . duplicate = id+> fmap extract . duplicate = id+> duplicate . duplicate = fmap duplicate . duplicate++In this case you may not rely on the ability to define 'fmap' in+terms of 'liftW'.++You may of course, choose to define both 'duplicate' /and/ 'extend'.+In that case you must also satisfy these laws:++> extend f = fmap f . duplicate+> duplicate = extend id+> fmap f = extend (f . extract)++These are the default definitions of 'extend' and 'duplicate' and+the definition of 'liftW' respectively.++-}++class Functor w => Comonad w where+ -- | -- > extract . fmap f = f . extract- extract :: w a -> a+ extract :: w a -> a --- | A suitable default definition for 'fmap' for a 'Comonad'. --- Promotes a function to a comonad.------ > fmap f = extend (f . extract)-liftW :: Comonad w => (a -> b) -> w a -> w b-liftW f = extend (f . extract)-{-# INLINE liftW #-}+ -- |+ -- > duplicate = extend id+ -- > fmap (fmap f) . duplicate = duplicate . fmap f+ duplicate :: w a -> w (w a)+ duplicate = extend id --- | Comonadic fixed point-wfix :: Comonad w => w (w a -> a) -> a-wfix w = extract w (extend wfix w)+ -- |+ -- > extend f = fmap f . duplicate+ extend :: (w a -> b) -> w a -> w b+ extend f = fmap f . duplicate --- * Comonads for Prelude types:------ Instances: While Control.Comonad.Instances would be more symmetric--- to the definition of Control.Monad.Instances in base, the reason--- the latter exists is because of Haskell 98 specifying the types--- @'Either' a@, @((,)m)@ and @((->)e)@ and the class Monad without--- having the foresight to require or allow instances between them.--- Here Haskell 98 says nothing about Comonads, so we can include the--- instances directly avoiding the wart of orphan instances. instance Comonad ((,)e) where+ duplicate p = (fst p, p) extract = snd -instance (Semigroup m, Monoid m) => Comonad ((->)m) where+instance Monoid m => Comonad ((->)m) where+ duplicate f m = f . mappend m extract f = f mempty --- * Comonads for types from 'transformers'.------ This isn't really a transformer, so i have no compunction about including the instance here.------ TODO: Petition to move Data.Functor.Identity into base instance Comonad Identity where+ duplicate = Identity extract = runIdentity --- Provided to avoid an orphan instance. Not proposed to standardize. --- If Comonad moved to base, consider moving instance into transformers? instance Comonad w => Comonad (IdentityT w) where+ extend f (IdentityT m) = IdentityT (extend (f . IdentityT) m) extract = extract . runIdentityT instance Comonad Tree where+ duplicate w@(Node _ as) = Node w (map duplicate as) extract (Node a _) = a +instance Comonad NonEmpty where+ extend f w@ ~(_ :| aas) = f w :| case aas of+ [] -> []+ (a:as) -> toList (extend f (a :| as))+ extract ~(a :| _) = a++-- | A @ComonadApply w@ is a strong lax symmetric semi-monoidal comonad on the+-- category @Hask@ of Haskell types.+--+-- That it to say that @w@ is a strong lax symmetric semi-monoidal functor on+-- Hask, where both extract and duplicate are symmetric monoidal natural+-- transformations.+--+-- Laws:+--+-- > (.) <$> u <@> v <@> w = u <@> (v <@> w)+-- > extract p (extract q) = extract (p <@> q)+-- > duplicate (p <*> q) = (\r s -> fmap (r <@> s)) <@> duplicate q <*> duplicate q+--+-- If our type is both a ComonadApply and Applicative we further require+--+-- > (<*>) = (<@>)+--+-- Finally, if you choose to define ('\<\@') and (\'@\>@), the results of your+-- definitions should match the following laws:+--+-- > a @> b = const id <$> a <@> b+-- > a <@ b = const <$> a <@> b++class Comonad w => ComonadApply w where+ (<@>) :: w (a -> b) -> w a -> w b++ (@>) :: w a -> w b -> w b+ a @> b = const id <$> a <@> b++ (<@) :: w a -> w b -> w a+ a <@ b = const <$> a <@> b++instance Semigroup m => ComonadApply ((,)m) where+ (m, f) <@> (n, a) = (m <> n, f a)+ (m, a) <@ (n, _) = (m <> n, a)+ (m, _) @> (n, b) = (m <> n, b)++instance ComonadApply NonEmpty where+ (<@>) = ap++instance Monoid m => ComonadApply ((->)m) where+ (<@>) = (<*>)+ (<@ ) = (<* )+ ( @>) = ( *>)++instance ComonadApply Identity where+ (<@>) = (<*>)+ (<@ ) = (<* )+ ( @>) = ( *>)++instance ComonadApply w => ComonadApply (IdentityT w) where+ IdentityT wa <@> IdentityT wb = IdentityT (wa <@> wb)++instance ComonadApply Tree where+ (<@>) = (<*>)+ (<@ ) = (<* )+ ( @>) = ( *>)++-- | A suitable default definition for 'fmap' for a 'Comonad'.+-- Promotes a function to a comonad.+--+-- > fmap f = liftW f = extend (f . extract)+liftW :: Comonad w => (a -> b) -> w a -> w b+liftW f = extend (f . extract)+{-# INLINE liftW #-}++-- | Comonadic fixed point à la Menendez+wfix :: Comonad w => w (w a -> a) -> a+wfix w = extract w (extend wfix w)++-- | Comonadic fixed point à la Orchard+cfix :: Comonad w => (w a -> a) -> w a+cfix f = fix (extend f)+{-# INLINE cfix #-}++-- | 'extend' with the arguments swapped. Dual to '>>=' for a 'Monad'.+(=>>) :: Comonad w => w a -> (w a -> b) -> w b+(=>>) = flip extend+{-# INLINE (=>>) #-}++-- | 'extend' in operator form+(<<=) :: Comonad w => (w a -> b) -> w a -> w b+(<<=) = extend+{-# INLINE (<<=) #-}++-- | Right-to-left Cokleisli composition+(=<=) :: Comonad w => (w b -> c) -> (w a -> b) -> w a -> c+f =<= g = f . extend g+{-# INLINE (=<=) #-}++-- | Left-to-right Cokleisli composition+(=>=) :: Comonad w => (w a -> b) -> (w b -> c) -> w a -> c+f =>= g = g . extend f+{-# INLINE (=>=) #-}++-- | A variant of '<@>' with the arguments reversed.+(<@@>) :: ComonadApply w => w a -> w (a -> b) -> w b+(<@@>) = liftW2 (flip id)+{-# INLINE (<@@>) #-}++-- | Lift a binary function into a comonad with zipping+liftW2 :: ComonadApply w => (a -> b -> c) -> w a -> w b -> w c+liftW2 f a b = f <$> a <@> b+{-# INLINE liftW2 #-}++-- | Lift a ternary function into a comonad with zipping+liftW3 :: ComonadApply w => (a -> b -> c -> d) -> w a -> w b -> w c -> w d+liftW3 f a b c = f <$> a <@> b <@> c+{-# INLINE liftW3 #-}+ -- | The 'Cokleisli' 'Arrow's of a given 'Comonad' newtype Cokleisli w a b = Cokleisli { runCokleisli :: w a -> b } +#ifdef __GLASGOW_HASKELL__ instance Typeable1 w => Typeable2 (Cokleisli w) where typeOf2 twab = mkTyConApp cokleisliTyCon [typeOf1 (wa twab)] where wa :: Cokleisli w a b -> w a wa = undefined+#endif cokleisliTyCon :: TyCon #if MIN_VERSION_base(4,4,0)@@ -124,7 +285,9 @@ instance Comonad w => ArrowChoice (Cokleisli w) where left = leftApp --- Cokleisli arrows are actually just a special case of a reader monad:+instance ComonadApply w => ArrowLoop (Cokleisli w) where+ loop (Cokleisli f) = Cokleisli (fst . wfix . extend f') where+ f' wa wb = f ((,) <$> wa <@> (snd <$> wb)) instance Functor (Cokleisli w a) where fmap f (Cokleisli g) = Cokleisli (f . g)@@ -137,50 +300,6 @@ return = Cokleisli . const Cokleisli k >>= f = Cokleisli $ \w -> runCokleisli (f (k w)) w -instance Comonad NonEmpty where- extract ~(a :| _) = a---{- $definition--There are two ways to define a comonad:--I. Provide definitions for 'extract' and 'extend'-satisfying these laws:--> extend extract = id-> extract . extend f = f-> extend f . extend g = extend (f . extend g)--In this case, you may simply set 'fmap' = 'liftW'.--These laws are directly analogous to the laws for monads-and perhaps can be made clearer by viewing them as laws stating-that Cokleisli composition must be associative, and has extract for-a unit:--> f =>= extract = f-> extract =>= f = f-> (f =>= g) =>= h = f =>= (g =>= h)--II. Alternately, you may choose to provide definitions for 'fmap',-'extract', and 'duplicate' satisfying these laws:--> extract . duplicate = id-> fmap extract . duplicate = id-> duplicate . duplicate = fmap duplicate . duplicate--In this case you may not rely on the ability to define 'fmap' in -terms of 'liftW'.--You may of course, choose to define both 'duplicate' /and/ 'extend'. -In that case you must also satisfy these laws:--> extend f = fmap f . duplicate-> duplicate = extend id-> fmap f = extend (f . extract)--These are the default definitions of 'extend' and'duplicate' and -the definition of 'liftW' respectively.---}+-- | Replace the contents of a functor uniformly with a constant value.+($>) :: Functor f => f a -> b -> f b+($>) = flip (<$)
− Data/Functor/Extend.hs
@@ -1,150 +0,0 @@-{-# LANGUAGE CPP #-}--------------------------------------------------------------------------------- |--- Module : Data.Functor.Extend--- Copyright : (C) 2011 Edward Kmett--- License : BSD-style (see the file LICENSE)------ Maintainer : Edward Kmett <ekmett@gmail.com>--- Stability : provisional--- Portability : portable---------------------------------------------------------------------------------module Data.Functor.Extend- ( -- * $definition- Extend(..)- , (=>>) -- :: Extend w => w a -> (w a -> b) -> w b- , (<<=) -- :: Extend w => (w a -> b) -> w a -> w b- , (=>=) -- :: Extend w => (w a -> b) -> (w b -> c) -> w a -> c- , (=<=) -- :: Extend w => (w b -> c) -> (w a -> b) -> w a -> c- ) where--import Prelude hiding (id, (.))-import Control.Category-import Control.Monad.Trans.Identity-import Data.Functor.Identity-import Data.Semigroup-import Data.List (tails)-import Data.List.NonEmpty (NonEmpty(..), toList)-import Data.Sequence (Seq) -import qualified Data.Sequence as Seq-import Data.Tree--infixl 1 =>> -infixr 1 <<=, =<=, =>= --class Functor w => Extend w where- -- | - -- > duplicate = extend id- -- > fmap (fmap f) . duplicate = duplicate . fmap f- duplicate :: w a -> w (w a)- -- |- -- > extend f = fmap f . duplicate- extend :: (w a -> b) -> w a -> w b-- extend f = fmap f . duplicate- duplicate = extend id---- | 'extend' with the arguments swapped. Dual to '>>=' for a 'Monad'.-(=>>) :: Extend w => w a -> (w a -> b) -> w b-(=>>) = flip extend-{-# INLINE (=>>) #-}---- | 'extend' in operator form -(<<=) :: Extend w => (w a -> b) -> w a -> w b-(<<=) = extend-{-# INLINE (<<=) #-}---- | Right-to-left Cokleisli composition -(=<=) :: Extend w => (w b -> c) -> (w a -> b) -> w a -> c-f =<= g = f . extend g-{-# INLINE (=<=) #-}---- | Left-to-right Cokleisli composition-(=>=) :: Extend w => (w a -> b) -> (w b -> c) -> w a -> c-f =>= g = g . extend f -{-# INLINE (=>=) #-}---- * Extends for Prelude types:------ Instances: While Data.Functor.Extend.Instances would be symmetric--- to the definition of Control.Monad.Instances in base, the reason--- the latter exists is because of Haskell 98 specifying the types--- @'Either' a@, @((,)m)@ and @((->)e)@ and the class Monad without--- having the foresight to require or allow instances between them.------ Here Haskell 98 says nothing about Extend, so we can include the--- instances directly avoiding the wart of orphan instances.--instance Extend [] where- duplicate = tails--instance Extend Maybe where- duplicate Nothing = Nothing- duplicate j = Just j--instance Extend (Either a) where- duplicate (Left a) = Left a- duplicate r = Right r--instance Extend ((,)e) where- duplicate p = (fst p, p)--instance Semigroup m => Extend ((->)m) where- duplicate f m = f . (<>) m--instance Extend Seq where- duplicate = Seq.tails--instance Extend Tree where- duplicate w@(Node _ as) = Node w (map duplicate as)---- I can't fix the world--- instance (Monoid m, Extend n) => Extend (ReaderT m n) --- duplicate f m = f . mappend m---- * Extends for types from 'transformers'.------ This isn't really a transformer, so i have no compunction about including the instance here.------ TODO: Petition to move Data.Functor.Identity into base-instance Extend Identity where- duplicate = Identity---- Provided to avoid an orphan instance. Not proposed to standardize. --- If Extend moved to base, consider moving instance into transformers?-instance Extend w => Extend (IdentityT w) where- extend f (IdentityT m) = IdentityT (extend (f . IdentityT) m)--instance Extend NonEmpty where- extend f w@ ~(_ :| aas) = f w :| case aas of- [] -> []- (a:as) -> toList (extend f (a :| as))--{- $definition--There are two ways to define an 'Extend' instance:--I. Provide definitions for 'extend'-satisfying this law:--> extend f . extend g = extend (f . extend g)--II. Alternately, you may choose to provide definitions for 'duplicate' -satisfying this laws:--> duplicate . duplicate = fmap duplicate . duplicate--These are both equivalent to the statement that (=>=) is associative--> (f =>= g) =>= h = f =>= (g =>= h)--You may of course, choose to define both 'duplicate' /and/ 'extend'. -In that case you must also satisfy these laws:--> extend f = fmap f . duplicate-> duplicate = extend id--These are the default definitions of 'extend' and 'duplicate'.---}
comonad.cabal view
@@ -1,6 +1,6 @@ name: comonad category: Control, Comonads-version: 1.1.1.6+version: 3.0 license: BSD3 cabal-version: >= 1.6 license-file: LICENSE@@ -27,10 +27,9 @@ base >= 4 && < 5, transformers >= 0.2 && < 0.4, containers >= 0.3 && < 0.6,- semigroups >= 0.8.3.1 && < 0.9+ semigroups >= 0.8.3 && < 0.8.4 exposed-modules: Control.Comonad- Data.Functor.Extend ghc-options: -Wall