abstract-par-0.3.3/0000755000000000000000000000000012236451154012271 5ustar0000000000000000abstract-par-0.3.3/abstract-par.cabal0000644000000000000000000000272012236451154015641 0ustar0000000000000000Name: abstract-par Version: 0.3.3 Synopsis: Type classes generalizing the functionality of the 'monad-par' library. -- Version history: -- 0.3 : Factored out of monad-par package. -- 0.3.1 : Relax deepseq restriction -- 0.3.3 : Minor: doc and formatting changes only. Description: The 'Par' monad offers a parallel programming API based on dataflow programming. To use the `Par` monad, install the @monad-par@ package, which includes this package as a dependency. . This package is an abstract interface only. It provides a number of type clasess, but not an implementation. The type classes separate different levels of @Par@ functionality. See the "Control.Monad.Par.Class" module for more details. Homepage: https://github.com/simonmar/monad-par License: BSD3 License-file: LICENSE Author: Ryan Newton Maintainer: Ryan Newton Copyright: (c) Ryan Newton 2011-2012 Stability: Experimental Category: Control,Parallelism,Monads Build-type: Simple Cabal-version: >=1.8 extra-source-files: Library Exposed-modules: -- A class generalizing different levels of monad-par functionality: Control.Monad.Par.Class -- A class providing unsafe functionality: , Control.Monad.Par.Unsafe Build-depends: base >= 4 && < 5 , deepseq >= 1.1 abstract-par-0.3.3/LICENSE0000644000000000000000000000275512236451154013307 0ustar0000000000000000Copyright Simon Marlow 2011 All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * 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. * Neither the name of Simon Marlow nor the names of other contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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. abstract-par-0.3.3/Setup.hs0000644000000000000000000000011012236451154013715 0ustar0000000000000000#!/usr/bin/env runhaskell import Distribution.Simple main = defaultMain abstract-par-0.3.3/Control/0000755000000000000000000000000012236451154013711 5ustar0000000000000000abstract-par-0.3.3/Control/Monad/0000755000000000000000000000000012236451154014747 5ustar0000000000000000abstract-par-0.3.3/Control/Monad/Par/0000755000000000000000000000000012236451154015471 5ustar0000000000000000abstract-par-0.3.3/Control/Monad/Par/Class.hs0000644000000000000000000001410312236451154017071 0ustar0000000000000000{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, CPP, FlexibleInstances, UndecidableInstances #-} -- UndecidableInstances {-| This module establishes a class hierarchy that captures the interfaces of @Par@ monads. There are two layers: simple futures ('ParFuture') and full @IVars@ ('ParIVar'). All @Par@ monads are expected to implement the former, some also implement the latter. For more documentation of the programming model, see * The "Control.Monad.Par" module in the @monad-par@ package. * The wiki\/tutorial () * The original paper () * Tutorial slides () * Other slides (, ) -} -- module Control.Monad.Par.Class ( -- * Futures ParFuture(..) -- * IVars , ParIVar(..) -- RRN: Not releasing this interface until there is a nice implementation of it: -- Channels (Streams) -- , ParChan(..) , NFData() -- This is reexported. ) where import Control.DeepSeq -------------------------------------------------------------------------------- -- | @ParFuture@ captures the class of Par monads which support -- futures. This level of functionality subsumes @par@/@pseq@ and is -- similar to the "Control.Parallel.Strategies.Eval" monad. -- -- A minimal implementation consists of `spawn_` and `get`. -- However, for monads that are also a member of `ParIVar` it is -- typical to simply define `spawn` in terms of `fork`, `new`, and `put`. class Monad m => ParFuture future m | m -> future where -- | Create a potentially-parallel computation, and return a /future/ -- (or /promise/) that can be used to query the result of the forked -- computataion. -- -- > spawn p = do -- > r <- new -- > fork (p >>= put r) -- > return r -- spawn :: NFData a => m a -> m (future a) -- | Like 'spawn', but the result is only head-strict, not fully-strict. spawn_ :: m a -> m (future a) -- | Wait for the result of a future, and then return it. get :: future a -> m a -- | Spawn a pure (rather than monadic) computation. Fully-strict. -- -- > spawnP = spawn . return spawnP :: NFData a => a -> m (future a) -- Default implementations: spawn p = spawn_ (do x <- p; deepseq x (return x)) spawnP a = spawn (return a) -------------------------------------------------------------------------------- -- | @ParIVar@ builds on futures by adding full /anyone-writes, anyone-reads/ IVars. -- These are more expressive but may not be supported by all distributed schedulers. -- -- A minimal implementation consists of `fork`, `put_`, and `new`. class ParFuture ivar m => ParIVar ivar m | m -> ivar where -- | Forks a computation to happen in parallel. The forked -- computation may exchange values with other computations using -- @IVar@s. fork :: m () -> m () -- | creates a new @IVar@ new :: m (ivar a) -- | put a value into a @IVar@. Multiple 'put's to the same @IVar@ -- are not allowed, and result in a runtime error. -- -- 'put' fully evaluates its argument, which therefore must be an -- instance of 'NFData'. The idea is that this forces the work to -- happen when we expect it, rather than being passed to the consumer -- of the @IVar@ and performed later, which often results in less -- parallelism than expected. -- -- Sometimes partial strictness is more appropriate: see 'put_'. -- put :: NFData a => ivar a -> a -> m () put v a = deepseq a (put_ v a) -- | like 'put', but only head-strict rather than fully-strict. put_ :: ivar a -> a -> m () -- Extra API routines that have default implementations: -- | creates a new @IVar@ that contains a value newFull :: NFData a => a -> m (ivar a) newFull a = deepseq a (newFull_ a) -- | creates a new @IVar@ that contains a value (head-strict only) newFull_ :: a -> m (ivar a) newFull_ a = do v <- new -- This is usually inefficient! put_ v a return v -------------------------------------------------------------------------------- -- class ParYieldable ?? -- TODO: I think we should add yield officially: -- Allows other parallel computations to progress. (should not be -- necessary in most cases). -- yield :: m () -------------------------------------------------------------------------------- -- | @ParChan@ provides communication via streams of values between -- computations in a Par monad. Channels in this case are split -- into separate send and receive ports. -- -- The critical thing to know about @Chan@s in @Par@ monads is that -- while the @recv@ method destructively advances the position of -- the consumer's \"cursor\" in the stream, this is only observable -- in the /local/ @Par@ thread. That is, at @fork@ points it is -- necessary to give the child computation a separate set of stream -- cursors so that it observes the same sequences as the parent. class Monad m => ParChan snd rcv m | m -> snd, m -> rcv where -- | Create a new communication channel, with separate send and receive ports. newChan :: m (snd a, rcv a) -- | Receive a message on a channel in a synchronous, blocking manner. recv :: rcv a -> m a -- | Send a message on a channel. This may or may not block. send :: snd a -> a -> m () ---------------------------------------------------------------------------------------------------- -- t1 :: P.Par Int -- If the ParIVar => ParFuture instance exists the following is sufficient: t1 :: (ParFuture v m) => m Int t1 = do x <- spawn (return 3) get x t2 :: (ParIVar v m) => m Int t2 = do x <- new put x "hi" return 3 -- TODO: SPECIALIZE generic routines for the default par monad (and possibly ParRNG)? -- SPECIALISE parMap :: (NFData b) => (a -> b) -> [a] -> Par [b] -- SPECIALISE parMapM :: (NFData b) => (a -> Par b) -> [a] -> Par [b] abstract-par-0.3.3/Control/Monad/Par/Unsafe.hs0000644000000000000000000000230112236451154017242 0ustar0000000000000000{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-} -- TODO: ADD Unsafe -- | Unsafe operations. NOT part of "Safe Haskell". -- -- These are "unsafe" (in the normal, Haskell sense) when used with a -- "runPar" of type `Par a -> a`. If used with a `runParIO` that -- stays in the IO monad, then they are simply dangerous. -- -- For the purposes of Safe Haskell, any module that imports this -- module becomes untrustworthy. module Control.Monad.Par.Unsafe ( ParUnsafe(..) ) where -- import Control.Monad.Par.Class -- | The class of Par monads that provide unsafe functionality. class ParUnsafe iv p | p -> iv where -- | Peek at the current contents of an 'IVar' in a nonblocking way. unsafePeek :: iv a -> p (Maybe a) -- | Attempt to put a value into an 'IVar'. If successful, return the -- value put. If something is already there, return it instead. unsafeTryPut :: iv a -> a -> p a -- | Lift an 'IO' operation into the Par monad. unsafeParIO :: IO a -> p a -- Aside: -- If the need ever arises we could also consider unsafeMultiplePut that -- would be able to change the current value of an IVar. It could -- cause big problems in the distributed case, however.