TypeCompose 0.0 → 0.1
raw patch · 5 files changed
+73/−47 lines, 5 files
Files
- CHANGES +10/−1
- TypeCompose.cabal +1/−1
- src/Control/Compose.hs +30/−22
- src/Control/DataDriven.hs +28/−22
- src/Control/Instances.hs +4/−1
CHANGES view
@@ -1,1 +1,10 @@-+Version 0.1:+* Renamed "Compose/Comp/unComp" to "O/O/unO".+* Renamed "onComp" to "inO"+* Renamed "mapSrc" to "mapCur", and renamed type parameter "src" to "cur",+ to avoid confusion with "Source" in Phooey's use of DataDriven.+* Swapped argument order to dd in DataDriven.+* Renamed "Updater" to "Action"+* Changed the Monoid (IO a) instance in Control.Instances to use "liftA2+ mappend" instead of "(*>)".+* Added unFlip, inFlip, inFlip2
TypeCompose.cabal view
@@ -1,5 +1,5 @@ Name: TypeCompose-Version: 0.0+Version: 0.1 Synopsis: Type composition classes & instances Category: Composition, Control Description:
src/Control/Compose.hs view
@@ -18,9 +18,9 @@ module Control.Compose ( Cofunctor(..)- , Compose(..), onComp+ , O(..), inO , StaticArrow(..)- , Flip(..)+ , Flip(..), inFlip, inFlip2 , ArrowAp(..) , App(..) ) where@@ -33,36 +33,38 @@ class Cofunctor acc where cofmap :: (a -> b) -> (acc b -> acc a) ---- | Composition of type constructors: unary & unary. Called \"g . f\" in+-- | Composition of type constructors: unary & unary. Called \"@g . f@\" in -- [1], section 5, but GHC won't parse that, nor will it parse any infix -- type operators in an export list. Haddock won't parse any type infixes--- at all.-newtype Compose g f a = Comp { unComp :: g (f a) }+-- at all. Meant to be used infix when Haddock is up to it or not involved.+newtype O g f a = O { unO :: g (f a) } --- | Apply a function within the 'Comp' constructor.-onComp :: (g (f a) -> g' (f' a')) -> ((Compose g f) a -> (Compose g' f') a')-onComp h = Comp . h . unComp+-- | Apply a function within the 'O' constructor.+inO :: (g (f a) -> g' (f' a')) -> ((O g f) a -> (O g' f') a')+inO h = O . h . unO -instance (Functor g, Functor f) => Functor (Compose g f) where- fmap h (Comp gf) = Comp (fmap (fmap h) gf)+instance (Functor g, Functor f) => Functor (O g f) where+ fmap h (O gf) = O (fmap (fmap h) gf) -instance (Applicative g, Applicative f) => Applicative (Compose g f) where- pure = Comp . pure . pure- Comp getf <*> Comp getx = Comp (liftA2 (<*>) getf getx)+instance (Applicative g, Applicative f) => Applicative (O g f) where+ pure x = O (pure (pure x))+ O getf <*> O getx = O (liftA2 (<*>) getf getx) --- instance (Functor g, Cofunctor f) => Cofunctor (Compose g f) where--- cofmap h (Comp gf) = Comp (fmap (cofmap h) gf)+-- instance (Functor g, Cofunctor f) => Cofunctor (O g f) where+-- cofmap h (O gf) = O (fmap (cofmap h) gf) -- Or this alternative. Having both yields "Duplicate instance -- declarations".-instance (Cofunctor g, Functor f) => Cofunctor (Compose g f) where- cofmap h (Comp gf) = Comp (cofmap (fmap h) gf)-+instance (Cofunctor g, Functor f) => Cofunctor (O g f) where+ cofmap h (O gf) = O (cofmap (fmap h) gf) +-- We can also make functors by composing /cofunctors/. GHC would+-- consider such a declaration to be in conflict with the the+-- composition-of-functors instance, because it doesn't take contexts into+-- account. Too bad. -- standard Monoid instance for Applicative applied to Monoid-instance (Applicative (Compose g f), Monoid a) => Monoid (Compose g f a) where+instance (Applicative (O g f), Monoid a) => Monoid (O g f a) where { mempty = pure mempty; mappend = (*>) } -- | Composition of type constructors: unary with binary.@@ -110,11 +112,17 @@ -- | Flip type arguments-newtype Flip (~>) b a = Flip (a ~> b)+newtype Flip (~>) b a = Flip { unFlip :: a ~> b } +inFlip :: ((a~>b) -> (a' ~~> b')) -> (Flip (~>) b a -> Flip (~~>) b' a')+inFlip f (Flip ar) = Flip (f ar)++inFlip2 :: ((a~>b) -> (a' ~~> b') -> (a'' ~~~> b''))+ -> (Flip (~>) b a -> Flip (~~>) b' a' -> Flip (~~~>) b'' a'')+inFlip2 f (Flip ar) (Flip ar') = Flip (f ar ar')+ instance Arrow (~>) => Cofunctor (Flip (~>) b) where cofmap h (Flip f) = Flip (arr h >>> f)- -- | Type application newtype App f a = App { unApp :: f a }
src/Control/DataDriven.hs view
@@ -16,9 +16,9 @@ module Control.DataDriven ( -- * Plumbing for \"events\" and subscription - Sink, Updater, News+ Sink, Action, News -- * Data-driven computations- , DataDrivenG, dd, mapSrc+ , DataDrivenG, dd, mapCur , DataDriven, runDD, joinDD ) where @@ -36,14 +36,14 @@ ----------------------------------------------------------} -- | Sinks (consumers) of values-type Sink src a = a -> Updater src+type Sink cur a = a -> Action cur --- | Updaters (actions)-type Updater src = src ()+-- | Actions+type Action cur = cur () -- | News publisher -- somewhere to register updaters to be executed -- when events occur.-type News src = Sink src (Updater src)+type News cur = Sink cur (Action cur) {----------------------------------------------------------@@ -51,40 +51,46 @@ ----------------------------------------------------------} -- | The general type of data-driven computations. Represented as a--- /news/ publisher (@news@) and a source of new values (@src@). Clients+-- /news/ publisher (@news@) and a way to get new values (@cur@). Clients -- interested in the value subscribe to @news@ and extract a new value--- from @src@ when notified that the value may have changed. When @news@--- is a monoid and @src@ is an applicative functor, @DataDriven news src@+-- from @cur@ when notified that the value may have changed. When @news@+-- is a monoid and @cur@ is an applicative functor, @DataDrivenG news cur@ -- is an applicative functor also. The applicative property is very -- convenient for composition. See the more specific type 'DataDriven'.+--+-- Nicer, but Haddock chokes on the infix op:+-- type DataDrivenG news cur = ((,) news) `O` cur -type DataDrivenG news src = Compose ((,) news) src+type DataDrivenG news cur = O ((,) news) cur +-- More tersely :+-- type DataDrivenG news = O ((,) news)+ -- | Construct a data-driven computation from a subscription service -- (@Monoid@) and a value source subscriber (@Applicative@).-dd :: news -> src a -> DataDrivenG news src a-dd = curry Comp+dd :: cur a -> news -> DataDrivenG news cur a+dd = flip (curry O) -- | Modify the source part of a 'DataDriven' computation.-mapSrc :: (src a -> src b) -> (DataDrivenG news src a -> DataDrivenG news src b)-mapSrc f = onComp (second f)+mapCur :: (cur a -> cur b) -> (DataDrivenG news cur a -> DataDrivenG news cur b)+mapCur f = inO (second f) -- | Data driven with news publisher-type DataDriven src = DataDrivenG (News src) src+type DataDriven cur = DataDrivenG (News cur) cur -- | Run a unit-valued 'DataDriven' computation. Causes the source to be -- executed /and/ registered with the subscriber.-runDD :: (Monoid (Updater src), Applicative src)- => DataDriven src () -> Updater src-runDD (Comp (news,src)) = news src `mappend` src+runDD :: (Monoid (Action cur), Applicative cur)+ => DataDriven cur () -> Action cur+runDD (O (news,cur)) = news cur `mappend` cur -- | Apply 'join' to a source-joinDD :: Monad src => DataDriven src (src a) -> DataDriven src a-joinDD = mapSrc join+joinDD :: Monad cur => DataDriven cur (cur a) -> DataDriven cur a+joinDD = mapCur join --- runDDJoin :: (Monad src, Applicative src, Monoid (Updater src))--- => DataDriven src (Updater src) -> Updater src+-- runDDJoin :: (Monad cur, Applicative cur, Monoid (Action cur))+-- => DataDriven cur (Action cur) -> Action cur -- runDDJoin = runDD . joinDD
src/Control/Instances.hs view
@@ -26,7 +26,10 @@ -- Standard instance: Applicative functor applied to monoid -instance Monoid a => Monoid (IO a) where { mempty = pure mempty; mappend = (*>) } +instance Monoid a => Monoid (IO a) where + mempty = pure mempty + mappend = liftA2 mappend + -- standard Applicative instance for Monad instance Monad m => Applicative (ReaderT r m) where { pure = return; (<*>) = ap }