packages feed

wires (empty) → 0.1.0

raw patch · 13 files changed

+876/−0 lines, 13 filesdep +basedep +clockdep +containerssetup-changed

Dependencies added: base, clock, containers, deepseq, profunctors, semigroupoids, these, wires

Files

+ CHANGELOG.md view
@@ -0,0 +1,3 @@+# 0.1.0++  * Initial version.
+ Control/Wire.hs view
@@ -0,0 +1,17 @@+-- |+-- Copyright:  (c) 2016 Ertugrul Söylemez+-- License:    BSD3+-- Maintainer: Ertugrul Söylemez <esz@posteo.de>+-- Stability:  experimental++module Control.Wire+    ( -- * Wires+      module Control.Category,+      module Control.Wire.Core,+      module Control.Wire.Utils+    )+    where++import Control.Category+import Control.Wire.Core+import Control.Wire.Utils
+ Control/Wire/Controller.hs view
@@ -0,0 +1,48 @@+-- |+-- Copyright:  (c) 2016 Ertugrul Söylemez+-- License:    BSD3+-- Maintainer: Ertugrul Söylemez <esz@posteo.de>+-- Stability:  experimental++{-# LANGUAGE TupleSections #-}++module Control.Wire.Controller+    ( -- * Controllers+      animate,+      control,+      newEvent,+      onEvent,+      stepWire+    )+    where++import Control.Wire.Internal+++-- | Run the given action in every frame.++animate :: (Applicative m) => Wire m (m a) a+animate = let w = Wire (fmap (, w)) in w+++-- | Run the given wire until its result event occurs.++control :: (Monad m) => Wire m () (Event b) -> m b+control w' = do+    (mx, w) <- stepWire w' ()+    event (control w) pure mx+++-- | Construct an event from the given polling function.++newEvent :: (Functor m) => Wire m (m (Maybe b)) (Event b)+newEvent = Wire $ fmap (\mx -> (maybe NotNow Now mx, newEvent))+++-- | Run the given action whenever the given event occurs.++onEvent :: (Applicative m) => Wire m (Event (m a)) (Event a)+onEvent =+    Wire $+    event (pure (NotNow, onEvent))+          (fmap $ \x -> (Now x, onEvent))
+ Control/Wire/Core.hs view
@@ -0,0 +1,157 @@+-- |+-- Copyright:  (c) 2016 Ertugrul Söylemez+-- License:    BSD3+-- Maintainer: Ertugrul Söylemez <esz@posteo.de>+-- Stability:  experimental++{-# LANGUAGE RankNTypes #-}++module Control.Wire.Core+    ( -- * Wires+      Wire,+      evalWith,+      initial,+      withM,++      -- * Events+      Event,+      catMapE,+      hold,+      hold',+      never,+      unfoldE,++      -- * Switching+      manage,+      manage',+      sequenceW,+      switch,+      switch'+    )+    where++import Control.Wire.Internal+++-- | Map and filter event occurrences using the given function.++catMapE :: (a -> Maybe b) -> Event a -> Event b+catMapE f = event NotNow (maybe NotNow Now . f)+++-- | Evaluate the input using the given strategy in every frame.  Valid+-- arguments include functions like `seq`.++evalWith :: (Applicative m) => (forall b. a -> b -> b) -> Wire m a a+evalWith strat = let w = Wire (\x -> x `strat` pure (x, w)) in w+++-- | Hold the latest occurrence of the given event starting with the+-- given initial value.  The value switch occurs in the next frame.++hold :: (Applicative m) => a -> Wire m (Event a) a+hold x' = delayW x' (hold' x')+++-- | Hold the latest occurrence of the given event starting with the+-- given initial value.  The value switch occurs instantly.++hold' :: (Applicative m) => a -> Wire m (Event a) a+hold' x' = Wire $ (\x -> pure (x, hold' x)) . event x' id+++-- | Run the given action once at the beginning.++initial :: (Applicative m) => Wire m (m a) a+initial = Wire $ fmap (\y -> (y, pure y))+++-- | Sequence each of the given wires and collect their results.  If the+-- given event occurs, the its function is applied to the current set of+-- wires.  Changes are applied in the next frame.++manage+    :: (Traversable f, Applicative m)+    => f (Wire m a b)+    -> Wire m (a, Event (f (Wire m a b) -> f (Wire m a b))) (f b)+manage ws' =+    Wire $ \(x, mf) ->+        (\ys -> (fst <$> ys,+                 manage (event id id mf (snd <$> ys))))+        <$> traverse (`stepWire` x) ws'+++-- | Sequence each of the given wires and collect their results.  If the+-- given event occurs, the its function is applied to the current set of+-- wires.  Changes are applied immediately.++manage'+    :: (Traversable f, Applicative m)+    => f (Wire m a b)+    -> Wire m (a, Event (f (Wire m a b) -> f (Wire m a b))) (f b)+manage' ws' =+    Wire $ \(x, mf) ->+        (\ys -> (fst <$> ys,+                 manage (snd <$> ys)))+        <$> traverse (`stepWire` x) (event id id mf ws')+++-- | The event that never occurs.++never :: Event a+never = NotNow+++-- | Sequence each of the given wires and collect their results.++sequenceW :: (Traversable f, Applicative m) => f (Wire m a b) -> Wire m a (f b)+sequenceW ws' =+    Wire $ \x ->+        (\ys -> (fst <$> ys,+                 sequenceW (snd <$> ys)))+        <$> traverse (\w' -> stepWire w' x) ws'+++-- | Acts like the given wire until its event occurs, then switches to+-- the wire the occurrence contained.  The switch occurs in the next+-- frame.++switch :: (Functor m) => Wire m a (b, Event (Wire m a b)) -> Wire m a b+switch w' =+    Wire $ \x ->+        (\((y, mw), w) -> (y, event (switch w) id mw))+        <$> stepWire w' x+++-- | Acts like the given wire until its event occurs, then switches to+-- the wire the occurrence contained.  The switch occurs immediately.++switch' :: (Monad m) => Wire m a (b, Event (Wire m a b)) -> Wire m a b+switch' w' =+    Wire $ \x -> do+        ((y, mw), w) <- stepWire w' x+        case mw of+          NotNow -> pure (y, switch w)+          Now nw -> stepWire nw x+++-- | Unfold the given event using the state transition functions it+-- carries.++unfoldE :: (Applicative m) => s -> Wire m (Event (s -> (a, s))) (Event a)+unfoldE s' =+    Wire $ \mf ->+        pure (case mf of+                NotNow -> (NotNow, unfoldE s')+                Now f  -> let (x, s) = f s' in (Now x, unfoldE s))+++-- | Run the given action to initialise the given wire.  Example:+--+-- > withM (scan f) actionFromInitialInput++withM :: (Monad m) => (s -> Wire m a b) -> (a -> m s) -> Wire m a b+withM w f =+    Wire $ \x -> do+        s0 <- f x+        stepWire (w s0) x
+ Control/Wire/Internal.hs view
@@ -0,0 +1,203 @@+-- |+-- Copyright:  (c) 2016 Ertugrul Söylemez+-- License:    BSD3+-- Maintainer: Ertugrul Söylemez <esz@posteo.de>+-- Stability:  experimental++{-# LANGUAGE DeriveFunctor #-}++module Control.Wire.Internal+    ( -- * Wires+      Wire(..),+      delayW,++      -- * Events+      Event(..),+      event+    )+    where++import Control.Arrow+import Control.Category+import Control.DeepSeq+import Control.Monad.Fix+import Data.Align+import Data.Functor.Bind+import Data.Functor.Extend+import Data.Functor.Plus+import Data.Profunctor+import Data.These+import Prelude hiding ((.), id)+++-- | An event is a timestamped stream of occurrences with payloads of+-- the given type.++data Event a+    = NotNow  -- ^ Not in this frame.+    | Now a   -- ^ In this frame with the given value.+    deriving (Functor)++instance Align Event where+    nil = NotNow++    alignWith f (Now x) (Now y) = Now (f (These x y))+    alignWith f (Now x) _       = Now (f (This x))+    alignWith f _       (Now y) = Now (f (That y))+    alignWith _ _       _       = NotNow++instance Alt Event where+    (<!>) = alignWith (mergeThese const)++instance Apply Event where+    Now f  <.> Now x  = Now (f x)+    _      <.> _      = NotNow++instance Bind Event where+    Now x  >>- f = event NotNow Now (f x)+    NotNow >>- _ = NotNow++    join (Now (Now x)) = Now x+    join _             = NotNow++instance Extend Event where+    duplicated = event NotNow (Now . Now)+    extended f = event NotNow (Now . f . Now)++instance (Monoid a) => Monoid (Event a) where+    mappend = alignWith (mergeThese mappend)+    mempty  = nil++instance (NFData a) => NFData (Event a) where+    rnf NotNow = ()+    rnf (Now x) = rnf x++instance Plus Event where+    zero = nil+++-- | 'Wire' is a language for defining reactive systems.  It is similar+-- to the underlying monad @m@, but runs continuously.++newtype Wire m a b =+    Wire {+      -- | Run a single frame of the given wire.+      stepWire :: a -> m (b, Wire m a b)+    }+    deriving (Functor)++instance (Applicative m) => Applicative (Wire m a) where+    pure x = let w = Wire (\_ -> pure (x, w)) in w++    wf' <*> wx' =+        Wire $ \x' ->+            (\(f, wf) (x, wx) -> (f x, wf <*> wx))+            <$> stepWire wf' x'+            <*> stepWire wx' x'++instance (Monad m) => Arrow (Wire m) where+    arr f = let w = Wire (\x -> pure (f x, w)) in w+    first = first'+    second = second'++    wx' &&& wy' =+        Wire $ \x' ->+            (\(x, wx) (y, wy) -> ((x, y), wx &&& wy))+            <$> stepWire wx' x'+            <*> stepWire wy' x'++    wx' *** wy' =+        Wire $ \(x', y') ->+            (\(x, wx) (y, wy) -> ((x, y), wx *** wy))+            <$> stepWire wx' x'+            <*> stepWire wy' y'++instance (Monad m) => ArrowChoice (Wire m) where+    left = left'+    right = right'++    wl' +++ wr' =+        Wire $+        either (\x -> (\(y, wl) -> (Left y,  wl +++ wr')) <$> stepWire wl' x)+               (\x -> (\(y, wr) -> (Right y, wl' +++ wr)) <$> stepWire wr' x)++    wl' ||| wr' =+        Wire $+        either (\x -> (\(y, wl) -> (y, wl ||| wr')) <$> stepWire wl' x)+               (\x -> (\(y, wr) -> (y, wl' ||| wr)) <$> stepWire wr' x)++instance (MonadFix m) => ArrowLoop (Wire m) where+    loop = unfirst++instance (Monad m) => Category (Wire m) where+    id = let w = Wire (\x -> pure (x, w)) in w++    w2' . w1' =+        Wire $ \x0 -> do+            (x1, w1) <- stepWire w1' x0+            (x2, w2) <- stepWire w2' x1+            pure (x2, w2 . w1)++instance (Applicative m) => Choice (Wire m) where+    left' w' =+        Wire $+        either (\x -> (\(y, w) -> (Left y, left' w)) <$> stepWire w' x)+               (\x -> pure (Right x, left' w'))++    right' w' =+        Wire $+        either (\x -> pure (Left x, right' w'))+               (\x -> (\(y, w) -> (Right y, right' w)) <$> stepWire w' x)++instance (MonadFix m) => Costrong (Wire m) where+    unfirst w' =+        Wire $ \x' ->+            (\((x, _), w) -> (x, unfirst w))+            <$> mfix (\r -> stepWire w' (x', snd (fst r)))++    unsecond w' =+        Wire $ \x' ->+            (\((_, x), w) -> (x, unsecond w))+            <$> mfix (\r -> stepWire w' (fst (fst r), x'))++instance (Functor m) => Profunctor (Wire m) where+    dimap fl fr = go+        where+        go w' = Wire (fmap (\(y, w) -> (fr y, go w)) . stepWire w' . fl)++    lmap f = go+        where+        go w' = Wire (fmap (\(y, w) -> (y, go w)) . stepWire w' . f)++    rmap = fmap++instance (Functor m) => Strong (Wire m) where+    first' w' =+        Wire $ \(x', y) ->+            (\(x, w) -> ((x, y), first' w))+            <$> stepWire w' x'++    second' w' =+        Wire $ \(x, y') ->+            (\(y, w) -> ((x, y), second' w))+            <$> stepWire w' y'+++-- | Delay the result of the given wire by one frame.++delayW :: (Functor m) => b -> Wire m a b -> Wire m a b+delayW y' w' =+    Wire $ \x ->+        (\(y, w) -> (y', delayW y w))+        <$> stepWire w' x+++-- | Fold the given event.++event+    :: r         -- ^ Not now.+    -> (a -> r)  -- ^ Now.+    -> Event a   -- ^ Event to fold.+    -> r+event k _ NotNow  = k+event _ k (Now x) = k x
+ Control/Wire/Utils.hs view
@@ -0,0 +1,56 @@+-- |+-- Copyright:  (c) 2016 Ertugrul Söylemez+-- License:    BSD3+-- Maintainer: Ertugrul Söylemez <esz@posteo.de>+-- Stability:  experimental++module Control.Wire.Utils+    ( -- * Wire utilities+      withM_,++      -- * Event utilities+      filterE,+      scan,+      scan',+      scanE+    )+    where++import Control.Category+import Control.Wire.Core+import Data.Profunctor+import Prelude hiding ((.), id)+++-- | Filter event occurrences using the given function.++filterE :: (a -> Bool) -> Event a -> Event a+filterE p = catMapE (\x -> if p x then Just x else Nothing)+++-- | Left scan and hold of the given event.++scan :: (Monad m) => a -> Wire m (Event (a -> a)) a+scan x0 = hold x0 . scanE x0+++-- | Left scan and hold of the given event.  The value switch occurs+-- instantly.++scan' :: (Monad m) => a -> Wire m (Event (a -> a)) a+scan' x0 = hold' x0 . scanE x0+++-- | Left scan of the given event.++scanE :: (Applicative m) => a -> Wire m (Event (a -> a)) (Event a)+scanE = lmap (fmap $ \f x -> let y = f x in (y, y)) . unfoldE+++-- | Run the given action to initialise the given wire.  Simplified+-- variant of 'withM'.  Example:+--+-- > withM_ (scan f) action++withM_ :: (Monad m) => (s -> Wire m a b) -> m s -> Wire m a b+withM_ w c = withM w (const c)
+ Control/Wire/Varying.hs view
@@ -0,0 +1,155 @@+-- |+-- Copyright:  (c) 2016 Ertugrul Söylemez+-- License:    BSD3+-- Maintainer: Ertugrul Söylemez <esz@posteo.de>+-- Stability:  experimental++{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveFoldable #-}+{-# LANGUAGE DeriveFunctor #-}++module Control.Wire.Varying+    ( -- * Time-varying values+      Varying,+      changes,+      value,++      -- * Events+      holdV,+      holdV',+      scanV,++      -- * Controllers+      animateV+    )+    where++import Control.Applicative+import Control.DeepSeq+import Control.Monad+import Control.Wire.Internal+import Data.String+#if MIN_VERSION_base(4,9,0)+import Numeric+#endif+++-- | A 'Varying' is a behaviour combined with an event that tracks when+-- the value changes.++data Varying a = Varying !Bool !a+    deriving (Foldable, Functor)++instance Applicative Varying where+    pure = Varying False+    (<*>) = ap++instance (Bounded a) => Bounded (Varying a) where+    minBound = pure minBound+    maxBound = pure maxBound++instance (NFData a) => NFData (Varying a) where+    rnf (Varying _ x) = rnf x++instance (Floating a) => Floating (Varying a) where+    (**) = liftA2 (**)+    pi = pure pi+    exp = fmap exp+    log = fmap log+    sqrt = fmap sqrt+    logBase = liftA2 logBase++    sin = fmap sin; asin = fmap asin; sinh = fmap sinh; asinh = fmap asinh+    cos = fmap cos; acos = fmap acos; cosh = fmap cosh; acosh = fmap acosh+    tan = fmap tan; atan = fmap atan; tanh = fmap tanh; atanh = fmap atanh++#if MIN_VERSION_base(4,9,0)+    log1p = fmap log1p+    expm1 = fmap expm1+    log1pexp = fmap log1pexp+    log1mexp = fmap log1mexp+#endif++instance (Fractional a) => Fractional (Varying a) where+    (/) = liftA2 (/)+    fromRational = pure . fromRational+    recip = fmap recip++instance (IsString a) => IsString (Varying a) where+    fromString = pure . fromString++instance Monad Varying where+    Varying cx x >>= f =+        let Varying cy y = f x+        in Varying (cx || cy) y++instance (Num a) => Num (Varying a) where+    (+) = liftA2 (+)+    (-) = liftA2 (-)+    (*) = liftA2 (*)+    abs = fmap abs+    fromInteger = pure . fromInteger+    negate = fmap negate+    signum = fmap signum+++-- | Run the given action each time the given time-varying value+-- changes.++animateV :: (Applicative m) => (a -> m b) -> Wire m (Varying a) (Varying b)+animateV f =+    Wire $ \(Varying cx x) -> do+        (\y -> (Varying cx y, go y))+        <$> f x++    where+    go y' =+        Wire $ \(Varying cx x) ->+            if cx+              then (\y -> (Varying True y, go y)) <$> f x+              else pure (Varying False y', go y')+++-- | The change event of the given time-varying value.++changes :: Varying a -> Event a+changes (Varying cx x) = if cx then Now x else NotNow+++-- | Hold the latest occurrence of the given event starting with the+-- given initial value.  The value switch occurs in the next frame.++holdV :: (Applicative m) => a -> Wire m (Event a) (Varying a)+holdV = go . Varying False+    where+    go x' =+        Wire $ \mx ->+            pure (x', go (event (Varying False (value x')) (Varying True) mx))+++-- | Hold the latest occurrence of the given event starting with the+-- given initial value.  The value switch occurs instantly.++holdV' :: (Applicative m) => a -> Wire m (Event a) (Varying a)+holdV' x' =+    Wire $ \mx ->+        pure $+        case mx of+          NotNow -> (Varying False x', holdV' x')+          Now x  -> (Varying True x, holdV' x)+++-- | Left scan and hold of the given event.++scanV :: (Applicative m) => (a -> b -> b) -> b -> Wire m (Event a) (Varying b)+scanV f = go . Varying False+    where+    go x' =+        Wire $ \mdx ->+            pure (x', go (event (Varying False) (\dx -> Varying True . f dx) mdx (value x')))+++-- | The behaviour value of the given time-varying value.++value :: Varying a -> a+value (Varying _ x) = x
+ LICENSE view
@@ -0,0 +1,27 @@+Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++    (1) Redistributions of source code must retain the above copyright+    notice, this list of conditions and the following disclaimer.++    (2) 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.++    (3)The name of the author may not be used to endorse or promote+    products derived from this software without specific prior written+    permission.++THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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,43 @@+Wires+=====++This is a functional reactive programming library for interactive+applications with the following features:++  * heavy focus on real-time applications like games and simulations,++  * very small core abstraction,++  * efficient in both time and space.++Until a proper tutorial has been written, please check out the+*examples* directory.  If you have questions, join #haskell-game on+irc.freenode.net.  If you would like to report a bug or request a+feature, please [file an+issue](https://github.com/esoeylemez/wires/issues).+++Module overview+---------------++The library is split into two roles: *applications* and *controllers*.+An application developer models interactions and implements reactive+systems, i.e. the application logic.  A controller developer implements+the glue between the application and the real world, i.e. how events and+time-varying values map to actual things on the screen or in the+network.  The module structure reflects that distinction:++Module                    | Purpose+--------------------------|-----------------------------------------------+`Control.Wire`            | Application language (basically core + utils).+`Control.Wire.Controller` | Controller language.+`Control.Wire.Core`       | Core application language.+`Control.Wire.Internal`   | You should never need this module.+`Control.Wire.Utils`      | Extra application utilities.++Modules not listed here are highly experimental and should not be used.++If you are asking yourself whether you are an application or a+controller developer: at this early stage of development you are+probably both, which means that you will write the application as well+as connect its inputs and outputs to the real world.
+ Setup.lhs view
@@ -0,0 +1,6 @@+> module Main (main) where+>+> import Distribution.Simple+>+> main :: IO ()+> main = defaultMain
+ examples/Utils.hs view
@@ -0,0 +1,29 @@+-- |+-- Copyright:  (c) 2016 Ertugrul Söylemez+-- License:    BSD3+-- Maintainer: Ertugrul Söylemez <esz@posteo.de>+-- Stability:  experimental++module Utils+    ( -- * Utilities+      average+    )+    where++import Control.Wire+import Data.Foldable+import Data.Profunctor+import qualified Data.Sequence as Seq+++-- | Average of the given event's payload over the last given number of+-- occurrences.++average :: (Fractional a, Monad m) => Int -> Wire m (Event a) (Event a)+average n =+    lmap (fmap go) (unfoldE Seq.empty)+    where+    go x xs' =+        let xs = Seq.take n (x Seq.<| xs')+        in (foldl' (+) 0 xs / fromIntegral (Seq.length xs),+            xs)
+ examples/ping-pong.hs view
@@ -0,0 +1,71 @@+-- |+-- Copyright:  (c) 2016 Ertugrul Söylemez+-- License:    BSD3+-- Maintainer: Ertugrul Söylemez <esz@posteo.de>+-- Stability:  experimental++{-# LANGUAGE Arrows #-}++module Main (main) where++import Control.Monad.IO.Class+import Control.Wire+import Control.Wire.Controller+import GHC.Stats+import Prelude hiding ((.), id)+import System.Clock+import System.IO+import System.Mem+import Text.Printf+import Utils+++newCharEvent :: (MonadIO m) => Wire m a (Event Char)+newCharEvent = proc _ ->+    newEvent -< liftIO $ do+        b <- hReady stdin+        if b then Just <$> getChar else pure Nothing+++newTickEvent :: (MonadIO m) => Wire m a (Event Double)+newTickEvent = proc _ -> do+    times <- newEvent -< Just <$> getT+    withM_ unfoldE getT -< fmap (\t t' -> (secs (t - t'), t)) times++    where+    secs = (/ 1000000000) . fromInteger . toNanoSecs+    getT = liftIO (getTime Monotonic)+++myApp :: (MonadIO m) => Wire m a (Event ())+myApp = proc _ -> do+    deltas <- newTickEvent -< ()+    fps <- hold 0 . (fmap recip <$> average 25) -< deltas+    chars <- newCharEvent -< ()++    acc <- scan 1 -< negate <$ filterE (== ' ') chars+    vel <- scan 0 -< fmap (\dt -> min 2 . max (-2) . (+ acc*dt)) deltas+    pos <- scan 0 -< fmap (\dt -> min 1 . max (-1) . (+ vel*dt)) deltas++    animate -< liftIO $ do+        performGC+        mem <- (`div` 1024) . currentBytesUsed <$> getGCStats+        printf "\r%8dk %8.2f %5.2f %s %s\027[K"+            mem+            fps+            vel+            (if acc > 0 then ">" else "<")+            (map (\xI ->+                      let x = -1 + 2 * fromInteger xI / 59+                      in if abs (pos - x) < 0.1 then 'X' else '.')+                 [0..59])+        hFlush stdout++    id -< () <$ filterE (== 'q') chars+++main :: IO ()+main = do+    hSetBuffering stdin NoBuffering+    hSetEcho stdin False+    control myApp
+ wires.cabal view
@@ -0,0 +1,61 @@+name:     wires+version:  0.1.0+category: Control, FRP+synopsis: Functional reactive programming library++maintainer:   Ertugrul Söylemez <esz@posteo.de>+author:       Ertugrul Söylemez <esz@posteo.de>+copyright:    Copyright 2016 Ertugrul Söylemez+homepage:     https://github.com/esoeylemez/wires+bug-reports:  https://github.com/esoeylemez/wires/issues+license:      BSD3+license-file: LICENSE++description:  Functional reactive programming library.++build-type:         Simple+cabal-version:      >= 1.10+extra-source-files: CHANGELOG.md README.md++source-repository head+    type:     git+    location: https://github.com/esoeylemez/wires.git++flag Examples+    default: False+    description: Build the example programs+    manual: True+++library+    build-depends:+        base                >= 4.8 && < 5,+        deepseq             >= 1.4 && < 2,+        profunctors         >= 5.2 && < 6,+        semigroupoids       >= 5.1 && < 6,+        these               >= 0.7 && < 1+    default-language: Haskell2010+    ghc-options: -W -fdefer-typed-holes+    exposed-modules:+        Control.Wire+        Control.Wire.Controller+        Control.Wire.Core+        Control.Wire.Internal+        Control.Wire.Utils+        Control.Wire.Varying++executable wires-ping-pong+    if flag(examples)+        build-depends:+            base >= 4.8 && < 5,+            clock,+            containers,+            profunctors,+            wires+    else+        buildable: False+    default-language: Haskell2010+    ghc-options: -threaded -fdefer-typed-holes+    hs-source-dirs: examples+    main-is: ping-pong.hs+    other-modules: Utils