packages feed

oath 0.0 → 0.1.1

raw patch · 4 files changed

+24/−10 lines, 4 filesdep ~basePVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base

API changes (from Hackage documentation)

+ Oath: tryOath :: Exception e => Oath a -> Oath (Either e a)
- Oath: hoistOath :: (forall x. STM x -> STM x) -> Oath a -> Oath a
+ Oath: hoistOath :: (STM a -> STM b) -> Oath a -> Oath b

Files

CHANGELOG.md view
@@ -1,5 +1,10 @@ # Revision history for oath -## 0.1.0.0 -- YYYY-mm-dd+## 0.1++* Generalised the type of `hoistOath`+* Added `tryOath`++## 0.0 -- YYYY-mm-dd  * First version. Released on an unsuspecting world.
README.md view
@@ -9,7 +9,7 @@  `Oath` is a continuation-passing IO action which takes a transaction to obtain the final result (`STM a`). The continuation-passing style makes it easier to release resources in time.-The easiest way to construct `Oath` is `oath`. It run the supplied action in a separate thread as long as the continuation is running.+The easiest way to construct `Oath` is `oath`. It runs the supplied IO action in a separate thread as long as the continuation is running.  ```haskell oath :: IO a -> Oath a@@ -23,7 +23,7 @@ evalOath m = runOath m atomically ``` -`Oath` is an `Applicative`, so you can combine multiple `Oath`s. It starts computations without waiting for the results. Run `evalOath` to get the final result. The following code run concurrently `foo :: IO a` and `bar :: IO b`, then applies `f` to these results.+`Oath` is an `Applicative`, so you can combine multiple `Oath`s using `<*>`. `Oath` combined this way kicks off computations without waiting for the results. The following code runs `foo :: IO a` and `bar :: IO b` concurrently, then applies `f` to these results.  ```haskell main = evalOath $ f <$> oath foo <*> oath bar@@ -40,7 +40,7 @@ Oath $ \cont -> bracket sendRequest cancelRequest (cont . waitForResponse) ``` -Timeout behaviour can be easily added using the `Alternative` instance and `delay :: Int -> Oath ()`. Or more in general, `<|>` runs both computations until one of them finishes.+Timeout behaviour can be easily added using the `Alternative` instance and `delay :: Int -> Oath ()`. `a <|> b` runs both computations until one of them returns a result, then cancels the other.  ```haskell -- | An 'Oath' that finishes once the given number of microseconds elapses@@ -62,7 +62,7 @@  [futures](https://hackage.haskell.org/package/futures-0.1/docs/Futures.html) provides a wrapper of `forkIO`. There is no way to terminate an action and it does not propagate exceptions. -[promise](https://hackage.haskell.org/package/promise-0.1.0.0/docs/Control-Concurrent-Promise.html) has illegal Applicative and Monad instances; `(<*>)` is not associative and has a bind that's not consistent with `(<*>).`+[promise](https://hackage.haskell.org/package/promise-0.1.0.0/docs/Control-Concurrent-Promise.html) has illegal Applicative and Monad instances; `(<*>)` is not associative and its `ap` is not consistent with `(<*>)`.  Performance ----
oath.cabal view
@@ -1,6 +1,6 @@ cabal-version:      2.4 name:               oath-version:            0.0+version:            0.1.1  -- A short (one-line) description of the package. synopsis:           Composable concurrent computation done right@@ -17,7 +17,7 @@ maintainer:         fumiexcel@gmail.com  -- A copyright notice.-copyright:          Copyright (c) 2021 Fumiaki Kinoshita+copyright:          Copyright (c) 2022 Fumiaki Kinoshita category:           Concurrency extra-source-files: CHANGELOG.md, README.md @@ -32,7 +32,7 @@      -- LANGUAGE extensions used by modules in this package.     -- other-extensions:-    build-depends:    base >=4.14.1.0 && <4.17, stm, stm-delay+    build-depends:    base >=4.14.1.0 && <4.18, stm, stm-delay     hs-source-dirs:   src     default-language: Haskell2010     ghc-options: -Wall -Wcompat
src/Oath.hs view
@@ -5,6 +5,7 @@   ( Oath(..)   , hoistOath   , evalOath+  , tryOath   , oath   , delay   , timeout) where@@ -21,16 +22,24 @@   deriving Functor   deriving (Semigroup, Monoid) via Ap Oath a -hoistOath :: (forall x. STM x -> STM x) -> Oath a -> Oath a+-- | Apply a function to the inner computation that waits for the result.+hoistOath :: (STM a -> STM b) -> Oath a -> Oath b hoistOath t (Oath m) = Oath $ \cont -> m $ cont . t +-- | Run an 'Oath' and wait for the result. evalOath :: Oath a -> IO a evalOath m = runOath m atomically +-- | Catch an exception thrown in the inner computation.+tryOath :: Exception e => Oath a -> Oath (Either e a)+tryOath = hoistOath $ \t -> fmap Right t `catchSTM` (pure . Left)++-- | ('<*>') initiates both computations, then combines the results once they are done instance Applicative Oath where   pure a = Oath $ \cont -> cont (pure a)   Oath m <*> Oath n = Oath $ \cont -> m $ \f -> n $ \x -> cont (f <*> x) +-- | ('<|>') waits for the first result, then cancel the loser instance Alternative Oath where   empty = Oath $ \cont -> cont empty   Oath m <|> Oath n = Oath $ \cont -> m $ \a -> n $ \b -> cont (a <|> b)@@ -49,6 +58,6 @@ delay :: Int -> Oath () delay dur = Oath $ \cont -> bracket (newDelay dur) cancelDelay (cont . waitDelay) --- | Wrap an 'Oath'+-- | Returns nothing if the 'Oath' does not finish within the given number of microseconds. timeout :: Int -> Oath a -> Oath (Maybe a) timeout dur m = Just <$> m <|> Nothing <$ delay dur