unamb 0.0.1 → 0.1.0
raw patch · 3 files changed
+66/−32 lines, 3 filesdep ~basePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base
API changes (from Hackage documentation)
+ Data.Unamb: bottom :: a
Files
- src/Data/Unamb.hs +61/−24
- unamb.cabal +1/−4
- wikipage.tw +4/−4
src/Data/Unamb.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE ScopedTypeVariables, RecursiveDo, CPP #-} {-# OPTIONS_GHC -Wall #-} ---------------------------------------------------------------------- -- |@@ -12,18 +12,24 @@ -- Unambiguous choice ---------------------------------------------------------------------- +#include "Typeable.h"+ module Data.Unamb (- unamb, amb, race, assuming, hang, asAgree+ bottom, unamb, assuming, asAgree, hang+ , amb, race ) where +import Prelude hiding (catch) -- For hang-import Control.Monad (forever)+-- import Control.Monad (forever) import System.IO.Unsafe --- For unamb+-- import Data.Dynamic+ import Control.Concurrent-import Control.Exception (evaluate)+import Control.Exception+ (evaluate, BlockedOnDeadMVar(..), catch, throw) -- | Unambiguous choice operator. Equivalent to the ambiguous choice@@ -43,35 +49,50 @@ -- whichever finishes first. See also 'amb'. Thanks to Spencer Janssen -- for this simple version. race :: IO a -> IO a -> IO a+ a `race` b = do v <- newEmptyMVar- ta <- forkIO (a >>= putMVar v)- tb <- forkIO (b >>= putMVar v)+ ta <- forkIO' (a >>= putMVar v)+ tb <- forkIO' (b >>= putMVar v) x <- takeMVar v killThread ta killThread tb return x --- Without using unsafePerformIO, is there a way to define a--- non-terminating but non-erroring pure value that consume very little--- resources while not terminating?+-- Use a particular exception as our representation for waiting forever.+-- A thread can bottom-out efficiently by throwing that exception. If both+-- threads bail out, then the 'takeMVar' would block. In that case, the+-- run-time system would notice and raise 'BlockedOnDeadMVar'. I'd then+-- want to convert that exception into the one that wait-forever+-- exception. As an expedient hack, I use 'BlockedOnDeadMVar' as the+-- wait-forever exception, so that no conversion is needed. Perhaps+-- revisit this choice, and define our own exception class, for clarity+-- and easier debugging. ++-- Fork a thread to execute a given action. Silence any raised exceptions.+forkIO' :: IO () -> IO ThreadId+forkIO' act = forkIO (act `catch` handler)+ where+ handler :: BlockedOnDeadMVar -> IO ()+ handler = const (return ())++-- I'd like @hang `unamb` hang@ to quickly terminate, throwing an+-- exception. I'm surprised that it doesn't lead to 'BlockedOnDeadMVar'.+-- Why doesn't it?? Oh -- maybe it does, when compiled.+++-- | A 'bottom' value, allowing no information out. A left- and right-+-- identity for 'unamb'. At the top level, evaluating 'bottom' results in+-- the message "Exception: thread blocked indefinitely".+bottom :: a+bottom = throw BlockedOnDeadMVar++-- {-# DEPRECATED hang "use bottom instead" #-}+ -- | Never yield an answer. Like 'undefined' or 'error "whatever"', but -- don't raise an error, and don't consume computational resources. hang :: a-hang = unsafePerformIO hangIO---- | Block forever.-hangIO :: IO a-hangIO = do -- putStrLn "warning: blocking forever."- -- Any never-terminating computation goes here- -- This one can yield an exception "thread blocked indefinitely"- -- newEmptyMVar >>= takeMVar- -- sjanssen suggests this alternative:- forever $ threadDelay maxBound- -- forever's return type is (), though it could be fully- -- polymorphic. Until it's fixed, I need the following line.- return undefined-+hang = bottom -- | Yield a value if a condition is true. Otherwise wait forever. assuming :: Bool -> a -> a@@ -80,3 +101,19 @@ -- | The value of agreeing values (or hang) asAgree :: Eq a => a -> a -> a a `asAgree` b = assuming (a == b) a++----++{-++data WaitForever = WaitForever++INSTANCE_TYPEABLE0(WaitForever,waitForeverTc,"WaitForever")++instance Show WaitForever where+ showsPrec _ WaitForever = showString "waiting for, like, evar"+instance Exception WaitForever++-}++----
unamb.cabal view
@@ -1,5 +1,5 @@ Name: unamb-Version: 0.0.1+Version: 0.1.0 Cabal-Version: >= 1.2 Synopsis: Unambiguous choice Category: Concurrency, Data, Other@@ -10,9 +10,6 @@ package in order to encourage experimentation. . Project wiki page: <http://haskell.org/haskellwiki/unamb>- .- The module documentation pages have links to colorized source code and- to wiki pages where you can read and contribute user comments. Enjoy! . © 2008 by Conal Elliott; BSD3 license. .
wikipage.tw view
@@ -7,9 +7,9 @@ <hask>unamb</hask> was originally a part of [[Reactive]]. I moved it to its own package in order to encourage experimentation. Besides this wiki page, here are more ways to find out about unamb:-* Read [http://code.haskell.org/unamb/doc/html/ the library documentation].-* Get the code repository: '''<tt>darcs get http://code.haskell.org/unamb</tt>'''.-* Install from [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/unamb Hackage].-* See the [[unamb/Versions| version history]].+* Visit the [http://hackage.haskell.org/cgi-bin/hackage-scripts/package/unamb Hackage page] for library documentation and to download & install.+* Or install with <tt>cabal install unamb</tt>.+* Get the code repository: <tt>darcs get http://code.haskell.org/unamb</tt>.+<!-- * See the [[unamb/Versions| version history]]. --> Please leave comments at the [[Talk:unamb|Talk page]].