packages feed

comonad 0.3.0 → 0.4.0

raw patch · 2 files changed

+214/−98 lines, 2 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

- Control.Comonad: class Comonad w => ComonadZip w
- Control.Comonad: instance ComonadZip Identity
- Control.Comonad: instance ComonadZip d => ArrowLoop (Cokleisli d)
- Control.Comonad: instance ComonadZip w => ComonadZip (IdentityT w)
- Control.Comonad: instance Monoid m => ComonadZip ((,) m)
- Control.Comonad: instance Monoid m => ComonadZip ((->) m)
- Control.Comonad: unfoldW :: Comonad w => (w b -> (a, b)) -> w b -> [a]
+ Control.Comonad: ($>) :: Functor f => f a -> b -> f b
+ Control.Comonad: (<$>) :: Functor f => (a -> b) -> f a -> f b
+ Control.Comonad: WrapApply :: Either (f a) a -> WrappedApply f a
+ Control.Comonad: WrappedApplicative :: f a -> WrappedApplicative f a
+ Control.Comonad: class (Comonad w, FunctorApply w) => ComonadApply w
+ Control.Comonad: class Functor f => FunctorApply f
+ Control.Comonad: instance Applicative (Cokleisli w a)
+ Control.Comonad: instance Applicative f => Applicative (WrappedApplicative f)
+ Control.Comonad: instance Applicative f => FunctorApply (WrappedApplicative f)
+ Control.Comonad: instance Arrow a => FunctorApply (WrappedArrow a b)
+ Control.Comonad: instance Comonad f => Comonad (WrappedApply f)
+ Control.Comonad: instance ComonadApply Identity
+ Control.Comonad: instance ComonadApply f => ComonadApply (WrappedApply f)
+ Control.Comonad: instance ComonadApply w => ArrowLoop (Cokleisli w)
+ Control.Comonad: instance ComonadApply w => ComonadApply (IdentityT w)
+ Control.Comonad: instance Functor f => Functor (WrappedApplicative f)
+ Control.Comonad: instance Functor f => Functor (WrappedApply f)
+ Control.Comonad: instance FunctorApply (Cokleisli w a)
+ Control.Comonad: instance FunctorApply IO
+ Control.Comonad: instance FunctorApply Identity
+ Control.Comonad: instance FunctorApply Maybe
+ Control.Comonad: instance FunctorApply ZipList
+ Control.Comonad: instance FunctorApply []
+ Control.Comonad: instance FunctorApply f => Applicative (WrappedApply f)
+ Control.Comonad: instance FunctorApply f => FunctorApply (WrappedApply f)
+ Control.Comonad: instance FunctorApply w => FunctorApply (IdentityT w)
+ Control.Comonad: instance Monad m => FunctorApply (WrappedMonad m)
+ Control.Comonad: instance Monoid m => ComonadApply ((,) m)
+ Control.Comonad: instance Monoid m => ComonadApply ((->) m)
+ Control.Comonad: instance Monoid m => FunctorApply ((,) m)
+ Control.Comonad: instance Monoid m => FunctorApply ((->) m)
+ Control.Comonad: instance Monoid m => FunctorApply (Const m)
+ Control.Comonad: liftF2 :: FunctorApply w => (a -> b -> c) -> w a -> w b -> w c
+ Control.Comonad: liftF3 :: FunctorApply w => (a -> b -> c -> d) -> w a -> w b -> w c -> w d
+ Control.Comonad: newtype WrappedApplicative f a
+ Control.Comonad: newtype WrappedApply f a
+ Control.Comonad: unwrapApplicative :: WrappedApplicative f a -> f a
+ Control.Comonad: unwrapApply :: WrappedApply f a -> Either (f a) a
- Control.Comonad: (.>) :: ComonadZip w => w a -> w b -> w b
+ Control.Comonad: (.>) :: FunctorApply f => f a -> f b -> f b
- Control.Comonad: (<.) :: ComonadZip w => w a -> w b -> w a
+ Control.Comonad: (<.) :: FunctorApply f => f a -> f b -> f a
- Control.Comonad: (<..>) :: ComonadZip w => w a -> w (a -> b) -> w b
+ Control.Comonad: (<..>) :: FunctorApply w => w a -> w (a -> b) -> w b
- Control.Comonad: (<.>) :: ComonadZip w => w (a -> b) -> w a -> w b
+ Control.Comonad: (<.>) :: FunctorApply f => f (a -> b) -> f a -> f b
- Control.Comonad: liftW2 :: ComonadZip w => (a -> b -> c) -> w a -> w b -> w c
+ Control.Comonad: liftW2 :: ComonadApply w => (a -> b -> c) -> w a -> w b -> w c
- Control.Comonad: liftW3 :: ComonadZip w => (a -> b -> c -> d) -> w a -> w b -> w c -> w d
+ Control.Comonad: liftW3 :: ComonadApply w => (a -> b -> c -> d) -> w a -> w b -> w c -> w d

Files

Control/Comonad.hs view
@@ -11,37 +11,36 @@ -- -- A 'Comonad' is the categorical dual of a 'Monad'. -----------------------------------------------------------------------------module Control.Comonad-  ( -  -- * Functor and Comonad+module Control.Comonad ( +  -- * Functors     Functor(..)-  , Comonad(..)-  -- * Functions--  -- ** Naming conventions-  -- $naming--  -- ** Operators-  , (=>=)   -- :: Comonad w => (w a -> b) -> (w b -> c) -> w a -> c-  , (=<=)   -- :: Comonad w => (w b -> c) -> (w a -> b) -> w a -> c-  , (=>>)   -- :: Comonad w => w a -> (w a -> b) -> w b-  , (<<=)   -- :: Comonad w => (w a -> b) -> w a -> w b+  , (<$>)     -- :: Functor f => (a -> b) -> f a -> f b+  , ( $>)     -- :: Functor f => f a -> b -> f b  -  -- * Fixed points and folds-  , wfix    -- :: Comonad w => w (w a -> a) -> a-  , unfoldW -- :: Comonad w => (w b -> (a,b)) -> w b -> [a]+  -- * Comonads+  , Comonad(..)+  , (=>=)     -- :: Comonad w => (w a -> b) -> (w b -> c) -> w a -> c+  , (=<=)     -- :: Comonad w => (w b -> c) -> (w a -> b) -> w a -> c+  , (=>>)     -- :: Comonad w => w a -> (w a -> b) -> w b+  , (<<=)     -- :: Comonad w => (w a -> b) -> w a -> w b+  , liftW     -- :: Comonad w => (a -> b) -> w a -> w b+  , wfix      -- :: Comonad w => w (w a -> a) -> a -  -- ** Comonadic lifting -  , liftW   -- :: Comonad w => (a -> b) -> w a -> w b+  -- * FunctorApply - strong lax symmetric semimonoidal endofunctors+  , FunctorApply(..)+  , (<..>)    -- :: FunctorApply w => w a -> w (a -> b) -> w b+  , liftF2    -- :: FunctorApply w => (a -> b -> c) -> w a -> w b -> w c+  , liftF3    -- :: FunctorApply w => (a -> b -> c -> d) -> w a -> w b -> w c -> w d -  -- * Comonads with Zipping-  , ComonadZip(..)-  , (<..>)  -- :: ComonadZip w => w a -> w (a -> b) -> w b-  , liftW2  -- :: ComonadZip w => (a -> b -> c) -> w a -> w b -> w c-  , liftW3  -- :: ComonadZip w => (a -> b -> c -> d) -> w a -> w b -> w c -> w d+  -- * ComonadApply - strong lax symmetric semimonoidal comonads+  , ComonadApply+  , 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+  -- * Wrappers   , Cokleisli(..)+  , WrappedApplicative(..)+  , WrappedApply(..)   ) where  import Prelude hiding (id, (.))@@ -55,9 +54,13 @@  infixl 1 =>>  infixr 1 <<=, =<=, =>= -infixl 4 <.>, <., .>, <..>+infixl 4 <.>, <., .>, <..>, $> -{-|+($>) :: Functor f => f a -> b -> f b+($>) = flip (<$)++{- |+ There are two ways to define a comonad:  I. Provide definitions for 'extract' and 'extend'@@ -96,22 +99,29 @@ > fmap f    = extend (f . extract)  These are the default definitions of 'extend' and'duplicate' and -the 'default' definition of 'liftW' respectively.+the definition of 'liftW' respectively.+ -}  class Functor w => Comonad w where-  -- | aka coreturn-  extract:: w a -> a-  -- | aka cojoin+  -- | +  -- > extract . fmap f = f . extract+  extract   :: w a -> a+  -- | +  -- > duplicate = extend id+  -- > fmap (fmap f) . duplicate = duplicate . fmap f   duplicate :: w a -> w (w a)-  -- | aka cobind-  extend :: (w a -> b) -> w a -> w b+  -- |+  -- > extend f  = fmap f . duplicate+  extend    :: (w a -> b) -> w a -> w b    extend f = fmap f . duplicate   duplicate = extend id  -- | 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 #-}@@ -136,20 +146,18 @@ f =>= g = g . extend f  {-# INLINE (=>=) #-} --- | A generalized comonadic list anamorphism-unfoldW :: Comonad w => (w b -> (a,b)) -> w b -> [a]-unfoldW f w = fst (f w) : unfoldW f (w =>> snd . f)- -- | Comonadic fixed point wfix :: Comonad w => w (w a -> a) -> a wfix w = extract w (extend wfix w)  -- * Comonads for Prelude types:---- Instances: While Control.Comonad.Instances would be more symmetric with 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: While Control.Comonad.Instances would be more symmetric+-- with 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@@ -161,7 +169,7 @@   duplicate f m = f . mappend m  -- * 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@@ -175,57 +183,183 @@   extract = extract . runIdentityT   extend f (IdentityT m) = IdentityT (extend (f . IdentityT) m) -{- | +-- | A strong lax symmetric semi-monoidal functor. -As a symmetric semi-monoidal comonad, an instance of ComonadZip is required to satisfy:+class Functor f => FunctorApply f where+  (<.>) :: f (a -> b) -> f a -> f b -> extract (a <.> b) = extract a (extract b)+  -- | a .> b = const id <$> a <.> b+  (.>) :: f a -> f b -> f b+  a .> b = const id <$> a <.> b -Minimal definition: '<.>'+  -- | a <. b = const <$> a <.> b+  (<.) :: f a -> f b -> f a+  a <. b = const    <$> a <.> b -Based on the ComonadZip from \"The Essence of Dataflow Programming\" -by Tarmo Uustalu and Varmo Vene, but adapted to fit the programming style of-Control.Applicative. +-- this only requires a Semigroup+instance Monoid m => FunctorApply ((,)m) where+  (<.>) = (<*>)+  (<. ) = (<* )+  ( .>) = ( *>) --}-class Comonad w => ComonadZip w where-  (<.>) :: w (a -> b) -> w a -> w b-  (.>) :: w a -> w b -> w b-  (<.) :: w a -> w b -> w a+-- this only requires a Semigroup+instance Monoid m => FunctorApply ((->)m) where+  (<.>) = (<*>)+  (<. ) = (<* )+  ( .>) = ( *>) -  a .> b = const id <$> a <.> b-  a <. b = const    <$> a <.> b-  -instance Monoid m => ComonadZip ((,)m) where+instance FunctorApply ZipList where   (<.>) = (<*>)+  (<. ) = (<* )+  ( .>) = ( *>) -instance Monoid m => ComonadZip ((->)m) where+instance FunctorApply [] where   (<.>) = (<*>)+  (<. ) = (<* )+  ( .>) = ( *>) -instance ComonadZip Identity where+instance FunctorApply IO where   (<.>) = (<*>)+  (<. ) = (<* )+  ( .>) = ( *>) -instance ComonadZip w => ComonadZip (IdentityT w) where+instance FunctorApply Maybe where+  (<.>) = (<*>)+  (<. ) = (<* )+  ( .>) = ( *>)++instance FunctorApply Identity where+  (<.>) = (<*>)+  (<. ) = (<* )+  ( .>) = ( *>)++instance FunctorApply w => FunctorApply (IdentityT w) where   IdentityT wa <.> IdentityT wb = IdentityT (wa <.> wb) +instance Monad m => FunctorApply (WrappedMonad m) where+  (<.>) = (<*>) +  (<. ) = (<* )+  ( .>) = ( *>)++instance Monoid m => FunctorApply (Const m) where+  (<.>) = (<*>) +  (<. ) = (<* )+  ( .>) = ( *>)++instance Arrow a => FunctorApply (WrappedArrow a b) where+  (<.>) = (<*>) +  (<. ) = (<* )+  ( .>) = ( *>)++-- | Wrap Applicatives to be used as a member of FunctorApply +newtype WrappedApplicative f a = WrappedApplicative { unwrapApplicative :: f a } ++instance Functor f => Functor (WrappedApplicative f) where+  fmap f (WrappedApplicative a) = WrappedApplicative (f <$> a)++instance Applicative f => FunctorApply (WrappedApplicative f) where+  WrappedApplicative f <.> WrappedApplicative a = WrappedApplicative (f <*> a)+  WrappedApplicative a <.  WrappedApplicative b = WrappedApplicative (a <*  b)+  WrappedApplicative a  .> WrappedApplicative b = WrappedApplicative (a  *> b)++instance Applicative f => Applicative (WrappedApplicative f) where+  pure = WrappedApplicative . pure+  WrappedApplicative f <*> WrappedApplicative a = WrappedApplicative (f <*> a)+  WrappedApplicative a <*  WrappedApplicative b = WrappedApplicative (a <*  b)+  WrappedApplicative a  *> WrappedApplicative b = WrappedApplicative (a  *> b)+  +-- | Transform a strong lax symmetric semi-monoidal endofunctor into a strong lax symmetric+-- monoidal endofunctor by adding a unit.+newtype WrappedApply f a = WrapApply { unwrapApply :: Either (f a) a }++instance Functor f => Functor (WrappedApply f) where+  fmap f (WrapApply (Right a)) = WrapApply (Right (f     a ))+  fmap f (WrapApply (Left fa)) = WrapApply (Left  (f <$> fa))++instance FunctorApply f => FunctorApply (WrappedApply f) where+  WrapApply (Right f) <.> WrapApply (Right a) = WrapApply (Right (f        a ))+  WrapApply (Right f) <.> WrapApply (Left fa) = WrapApply (Left  (f    <$> fa))+  WrapApply (Left ff) <.> WrapApply (Right a) = WrapApply (Left  (($a) <$> ff))+  WrapApply (Left ff) <.> WrapApply (Left fa) = WrapApply (Left  (ff   <.> fa))++  WrapApply a         <. WrapApply (Right _) = WrapApply a+  WrapApply (Right a) <. WrapApply (Left fb) = WrapApply (Left (a  <$ fb))+  WrapApply (Left fa) <. WrapApply (Left fb) = WrapApply (Left (fa <. fb))++  WrapApply (Right _) .> WrapApply b = WrapApply b+  WrapApply (Left fa) .> WrapApply (Right b) = WrapApply (Left (fa $> b ))+  WrapApply (Left fa) .> WrapApply (Left fb) = WrapApply (Left (fa .> fb))+  +instance FunctorApply f => Applicative (WrappedApply f) where+  pure a = WrapApply (Right a)+  (<*>) = (<.>)+  (<* ) = (<. )+  ( *>) = ( .>)++instance Comonad f => Comonad (WrappedApply f) where+  extract (WrapApply (Right a)) = a+  extract (WrapApply (Left fa)) = extract fa+  duplicate w@(WrapApply Right{}) = WrapApply (Right w)+  duplicate (WrapApply (Left fa)) = WrapApply (Left (extend (WrapApply . Left) fa))++instance ComonadApply f => ComonadApply (WrappedApply f)+   -- | A variant of '<.>' with the arguments reversed.-(<..>) :: ComonadZip w => w a -> w (a -> b) -> w b-(<..>) = liftW2 (flip id)+(<..>) :: FunctorApply w => w a -> w (a -> b) -> w b+(<..>) = liftF2 (flip id) {-# INLINE (<..>) #-}  -- | Lift a binary function into a comonad with zipping-liftW2 :: ComonadZip w => (a -> b -> c) -> w a -> w b -> w c-liftW2 f a b = f <$> a <.> b+liftF2 :: FunctorApply w => (a -> b -> c) -> w a -> w b -> w c+liftF2 f a b = f <$> a <.> b+{-# INLINE liftF2 #-}++-- | Lift a ternary function into a comonad with zipping+liftF3 :: FunctorApply w => (a -> b -> c -> d) -> w a -> w b -> w c -> w d+liftF3 f a b c = f <$> a <.> b <.> c+{-# INLINE liftF3 #-}++{- | ++A strong lax symmetric semi-monoidal comonad. As such an instance of +'ComonadApply' is required to satisfy:++> extract (a <.> b) = extract a (extract b)++This class is based on ComonadZip from \"The Essence of Dataflow Programming\" +by Tarmo Uustalu and Varmo Vene, but adapted to fit the programming style of+Control.Applicative. 'Applicative' can be seen as a similar law over and above +FunctorApply that:++> pure (a b) = pure a <.> pure b++-}++class (Comonad w, FunctorApply w) => ComonadApply w+-- | Only requires a Semigroup, but no such class exists+instance Monoid m => ComonadApply ((,)m)+-- | Only requires a Semigroup, but no such class exists+instance Monoid m => ComonadApply ((->)m)+instance ComonadApply Identity+instance ComonadApply w => ComonadApply (IdentityT w)++-- | Lift a binary function into a comonad with zipping+liftW2 :: ComonadApply w => (a -> b -> c) -> w a -> w b -> w c+liftW2 = liftF2 {-# INLINE liftW2 #-}  -- | Lift a ternary function into a comonad with zipping-liftW3 :: ComonadZip w => (a -> b -> c -> d) -> w a -> w b -> w c -> w d-liftW3 f a b c = f <$> a <.> b <.> c+liftW3 :: ComonadApply w => (a -> b -> c -> d) -> w a -> w b -> w c -> w d+liftW3 = liftF3 {-# INLINE liftW3 #-}  -- | The 'Cokleisli' 'Arrow's of a given 'Comonad' newtype Cokleisli w a b = Cokleisli { runCokleisli :: w a -> b } +instance Comonad w => Category (Cokleisli w) where+  id = Cokleisli extract+  Cokleisli f . Cokleisli g = Cokleisli (f =<= g)+ instance Comonad w => Arrow (Cokleisli w) where   arr f = Cokleisli (f . extract)   first f = f *** id@@ -233,46 +367,28 @@   Cokleisli f *** Cokleisli g = Cokleisli (f . fmap fst &&& g . fmap snd)   Cokleisli f &&& Cokleisli g = Cokleisli (f &&& g) -instance Comonad w => Category (Cokleisli w) where-  id = Cokleisli extract-  Cokleisli f . Cokleisli g = Cokleisli (f =<= g)- instance Comonad w => ArrowApply (Cokleisli w) where   app = Cokleisli $ \w -> runCokleisli (fst (extract w)) (snd <$> w)  instance Comonad w => ArrowChoice (Cokleisli w) where   left = leftApp -instance ComonadZip d => ArrowLoop (Cokleisli d) where+instance ComonadApply w => ArrowLoop (Cokleisli w) where   loop (Cokleisli f) = Cokleisli (fst . wfix . extend f') where      f' wa wb = f ((,) <$> wa <.> (snd <$> wb)) +-- Cokleisli arrows are actually just a special case of a reader monad:+ instance Functor (Cokleisli w a) where   fmap f (Cokleisli g) = Cokleisli (f . g) -instance Monad (Cokleisli w a) where-  return a = Cokleisli (const a)-  Cokleisli k >>= f = Cokleisli $ \w -> runCokleisli (f (k w)) w--{- $naming--The functions in this library use the following naming conventions, based-on those of Control.Monad.--* A postfix \'@W@\' always stands for a function in the Cokleisli category:-  The monad type constructor @w@ is added to function results-  (modulo currying) and nowhere else.  So, for example, -->  filter  ::              (a ->   Bool) -> [a] ->   [a]->  filterW :: Comonad w => (w a -> Bool) -> w [a] -> [a]--* A prefix \'@w@\' generalizes an existing function to a comonadic form.-  Thus, for example: -->  fix  :: (a -> a) -> a->  wfix :: w (w a -> a) -> a+instance FunctorApply (Cokleisli w a) where+  Cokleisli f <.> Cokleisli a = Cokleisli (\w -> (f w) (a w)) -When ambiguous, consistency with existing Control.Monad combinator naming -supercedes these rules (e.g. 'liftW')+instance Applicative (Cokleisli w a) where+  pure = Cokleisli . const+  Cokleisli f <*> Cokleisli a = Cokleisli (\w -> (f w) (a w)) --}+instance Monad (Cokleisli w a) where+  return = Cokleisli . const+  Cokleisli k >>= f = Cokleisli $ \w -> runCokleisli (f (k w)) w
comonad.cabal view
@@ -1,6 +1,6 @@ name:          comonad category:      Control, Comonads-version:       0.3.0+version:       0.4.0 license:       BSD3 cabal-version: >= 1.2 license-file:  LICENSE