forkable-monad 0.1.1 → 0.2.0.0
raw patch · 5 files changed
+145/−168 lines, 5 filesdep ~basesetup-changednew-uploaderPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base
API changes (from Hackage documentation)
- Control.Concurrent.Forkable: instance ForkableMonad IO
- Control.Concurrent.Forkable: instance ForkableMonad m => ForkableMonad (ReaderT r m)
- Control.Concurrent.Forkable: instance ForkableMonad m => ForkableMonad (StateT s m)
+ Control.Concurrent.Forkable: instance Control.Concurrent.Forkable.ForkableMonad GHC.Types.IO
+ Control.Concurrent.Forkable: instance Control.Concurrent.Forkable.ForkableMonad m => Control.Concurrent.Forkable.ForkableMonad (Control.Monad.Trans.Reader.ReaderT r m)
+ Control.Concurrent.Forkable: instance Control.Concurrent.Forkable.ForkableMonad m => Control.Concurrent.Forkable.ForkableMonad (Control.Monad.Trans.State.Lazy.StateT s m)
- Control.Concurrent.Forkable: class Monad m => ForkableMonad m
+ Control.Concurrent.Forkable: class (Monad m) => ForkableMonad m
Files
- Control/Concurrent/Forkable.hs +0/−112
- LICENSE +1/−1
- Setup.hs +0/−1
- forkable-monad.cabal +32/−54
- src/Control/Concurrent/Forkable.hs +112/−0
− Control/Concurrent/Forkable.hs
@@ -1,112 +0,0 @@--- Copyright 2010 Google Inc.------ Author: David Anderson <dave@natulte.net>------ See LICENSE and forkable-monad.cabal for authorship and licensing--- information.---- | This module defines a generic version of @Control.Concurrent@'s--- 'C.forkIO', which can directly run some complex monadic actions as--- well as plain 'IO' actions.------ @Control.Concurrent@'s 'C.forkIO' accepts an 'IO' computation only,--- and requires the caller to reconstruct the full monadic stack by--- hand in the new thread. In contrast, this module's 'forkIO' runs a--- computation in the same monad as the parent thread, transparently--- transplanting the monad stack to the new thread.------ For example, the following code which uses @Control.Concurrent@'s--- 'C.forkIO':------ > type MyMonad = ReaderT Int (StateT String IO)--- >--- > forkAndDo :: MyMonad ThreadId--- > forkAndDo = do--- > r <- ask--- > s <- lift get--- > liftIO $ forkIO $ (runStateT (runReaderT forkedDo r) s >> return ())--- >--- > forkedDo :: MyMonad ()--- > forkedDo = liftIO $ putStrLn "forkedDo running"------ can be reexpressed with this module's 'forkIO' as:------ > type MyMonad = ReaderT Int (StateT String IO)--- >--- > forkAndDo :: MyMonad ThreadId--- > forkAndDo = forkIO forkedDo--- >--- > forkedDo :: MyMonad ()--- > forkedDo = liftIO $ putStrLn "forkedDo running"------ 'forkIO' can operate on any monad that is an instance of--- 'ForkableMonad'. 'ForkableMonad' instances are defined for--- 'ReaderT' and 'StateT', as well as 'IO'. Here is the precise--- meaning of \"transplant\" for each of these:------ * 'IO' requires no special work, since @Control.Concurrent@'s--- 'C.forkIO' already provides the \"transplanting\" of an 'IO'--- action to a new thread.------ * 'ReaderT' makes the parent thread's environment available for--- consultation in the new thread.------ * 'StateT' makes a /copy/ of the parent thread's state available--- in the new thread. The states in the two threads are not--- linked, so it is expected that they will diverge as each thread--- updates its own copy of the state.------ Other standard transformers (notably @WriterT@, @ErrorT@ and--- @RWST@) do not have an instance defined, because those instances--- can only be defined through data loss.------ For example, the current output of a @Writer@ cannot be accessed--- from within the monad, so the best that can be done is to create a--- new pristine @Writer@ state for the new thread, and to discard all--- data written in that thread when the thread terminates.------ If you want to use 'forkIO' on a monad stack that includes one of--- these lossy monads, you will need to define the 'ForkableMonad'--- instances yourself. The same goes for any custom monads you may--- have in the stack.------ This module reexports @Control.Concurrent@ overlayed with the--- generic 'forkIO', so you can simply change your import from--- @Control.Concurrent@ to @Control.Concurrent.Forkable@ to use this--- module's 'forkIO' in your existing concurrent code.-module Control.Concurrent.Forkable- ( ForkableMonad (forkIO)- , module Control.Concurrent- ) where--import qualified Control.Concurrent as C-import Control.Concurrent hiding (forkIO)-import Control.Monad.Trans.Class-import Control.Monad.Trans.Reader-import Control.Monad.Trans.State--class (Monad m) => ForkableMonad m where- -- | Spark off a new thread to run the monadic computation passed- -- as the first argument, and return the 'ThreadId' of the newly- -- created thread.- --- -- The new thread will run the computation using the same monadic- -- context as the parent thread.- --- -- As a convenience, this forkIO accepts a computation returning- -- any value, not just unit. This value is discarded when the- -- computation terminates.- forkIO :: m a -> m C.ThreadId--instance ForkableMonad IO where- forkIO act = C.forkIO (act >> return ())--instance (ForkableMonad m) => ForkableMonad (ReaderT r m) where- forkIO act = do- env <- ask- lift $ forkIO (runReaderT act env)--instance (ForkableMonad m) => ForkableMonad (StateT s m) where- forkIO act = do- st <- get- lift $ forkIO (runStateT act st)
LICENSE view
@@ -1,5 +1,5 @@ Copyright David Anderson 2010-+ Matthew Ahrens 2018 All rights reserved. Redistribution and use in source and binary forms, with or without
Setup.hs view
@@ -1,3 +1,2 @@-#!/usr/bin/env runhaskell import Distribution.Simple main = defaultMain
forkable-monad.cabal view
@@ -1,57 +1,35 @@--- The name of the package.-Name: forkable-monad---- The package version. See the Haskell package versioning policy--- (http://www.haskell.org/haskellwiki/Package_versioning_policy) for--- standards guiding when and how versions should be incremented.-Version: 0.1.1---- A short (one-line) description of the package.-Synopsis: An implementation of forkIO for monad stacks.--Description:- This module defines a more generic version of Control.Concurrent's- forkIO, which can directly run some complex monadic actions as well- as plain IO actions.----- URL for the project homepage or repository.-Homepage: http://code.google.com/p/forkable-monad/---- The license under which the package is released.-License: BSD3---- The file containing the license text.-License-file: LICENSE---- The package copyright.-Copyright: Google Inc. 2010---- The package author(s).-Author: David Anderson---- An email address to which users can send suggestions, bug reports,--- and patches.-Maintainer: dave@natulte.net---- Stability of the pakcage (experimental, provisional, stable...)-Stability: Experimental--Category: Concurrent--Build-type: Simple---- Constraint on the version of Cabal needed to build this package.-Cabal-version: >=1.2+-- This file has been generated from package.yaml by hpack version 0.20.0.+--+-- see: https://github.com/sol/hpack+--+-- hash: 057d84219a4fe2319349d86c810abcc4dbf468e73a7b75754711cf197639f552 -Library- -- Modules exported by the library.- Exposed-modules: Control.Concurrent.Forkable+name: forkable-monad+version: 0.2.0.0+synopsis: An implementation of forkIO for monad stacks.+description: < This module defines a more generic version of Control.Concurrent's forkIO, which can directly run some complex monadic actions as well as plain IO actions.+homepage: https://github.com/https://www.github.com/System-Indystress/ForkableMonad#readme+bug-reports: https://github.com/https://www.github.com/System-Indystress/ForkableMonad/issues+author: David Anderson+maintainer: matt.p.ahrens@gmail.com+copyright: Google 2010; SID.run 2018+license: BSD3+license-file: LICENSE+build-type: Simple+cabal-version: >= 1.10 - -- Packages needed in order to build this package.- Build-depends: base >3.0 && <4.4,- transformers >=0.2.2+source-repository head+ type: git+ location: https://github.com/https://www.github.com/System-Indystress/ForkableMonad - -- Compiler options, for normal and profiling builds.- Ghc-options: -Wall- Ghc-prof-options: -auto-all+library+ hs-source-dirs:+ src+ build-depends:+ base >=4.7 && <5+ , transformers >=0.2.2+ exposed-modules:+ Control.Concurrent.Forkable+ other-modules:+ Paths_forkable_monad+ default-language: Haskell2010
+ src/Control/Concurrent/Forkable.hs view
@@ -0,0 +1,112 @@+-- Copyright 2010 Google Inc.+--+-- Author: David Anderson <dave@natulte.net>+--+-- See LICENSE and forkable-monad.cabal for authorship and licensing+-- information.++-- | This module defines a generic version of @Control.Concurrent@'s+-- 'C.forkIO', which can directly run some complex monadic actions as+-- well as plain 'IO' actions.+--+-- @Control.Concurrent@'s 'C.forkIO' accepts an 'IO' computation only,+-- and requires the caller to reconstruct the full monadic stack by+-- hand in the new thread. In contrast, this module's 'forkIO' runs a+-- computation in the same monad as the parent thread, transparently+-- transplanting the monad stack to the new thread.+--+-- For example, the following code which uses @Control.Concurrent@'s+-- 'C.forkIO':+--+-- > type MyMonad = ReaderT Int (StateT String IO)+-- >+-- > forkAndDo :: MyMonad ThreadId+-- > forkAndDo = do+-- > r <- ask+-- > s <- lift get+-- > liftIO $ forkIO $ (runStateT (runReaderT forkedDo r) s >> return ())+-- >+-- > forkedDo :: MyMonad ()+-- > forkedDo = liftIO $ putStrLn "forkedDo running"+--+-- can be reexpressed with this module's 'forkIO' as:+--+-- > type MyMonad = ReaderT Int (StateT String IO)+-- >+-- > forkAndDo :: MyMonad ThreadId+-- > forkAndDo = forkIO forkedDo+-- >+-- > forkedDo :: MyMonad ()+-- > forkedDo = liftIO $ putStrLn "forkedDo running"+--+-- 'forkIO' can operate on any monad that is an instance of+-- 'ForkableMonad'. 'ForkableMonad' instances are defined for+-- 'ReaderT' and 'StateT', as well as 'IO'. Here is the precise+-- meaning of \"transplant\" for each of these:+--+-- * 'IO' requires no special work, since @Control.Concurrent@'s+-- 'C.forkIO' already provides the \"transplanting\" of an 'IO'+-- action to a new thread.+--+-- * 'ReaderT' makes the parent thread's environment available for+-- consultation in the new thread.+--+-- * 'StateT' makes a /copy/ of the parent thread's state available+-- in the new thread. The states in the two threads are not+-- linked, so it is expected that they will diverge as each thread+-- updates its own copy of the state.+--+-- Other standard transformers (notably @WriterT@, @ErrorT@ and+-- @RWST@) do not have an instance defined, because those instances+-- can only be defined through data loss.+--+-- For example, the current output of a @Writer@ cannot be accessed+-- from within the monad, so the best that can be done is to create a+-- new pristine @Writer@ state for the new thread, and to discard all+-- data written in that thread when the thread terminates.+--+-- If you want to use 'forkIO' on a monad stack that includes one of+-- these lossy monads, you will need to define the 'ForkableMonad'+-- instances yourself. The same goes for any custom monads you may+-- have in the stack.+--+-- This module reexports @Control.Concurrent@ overlayed with the+-- generic 'forkIO', so you can simply change your import from+-- @Control.Concurrent@ to @Control.Concurrent.Forkable@ to use this+-- module's 'forkIO' in your existing concurrent code.+module Control.Concurrent.Forkable+ ( ForkableMonad (forkIO)+ , module Control.Concurrent+ ) where++import qualified Control.Concurrent as C+import Control.Concurrent hiding (forkIO)+import Control.Monad.Trans.Class+import Control.Monad.Trans.Reader+import Control.Monad.Trans.State++class (Monad m) => ForkableMonad m where+ -- | Spark off a new thread to run the monadic computation passed+ -- as the first argument, and return the 'ThreadId' of the newly+ -- created thread.+ --+ -- The new thread will run the computation using the same monadic+ -- context as the parent thread.+ --+ -- As a convenience, this forkIO accepts a computation returning+ -- any value, not just unit. This value is discarded when the+ -- computation terminates.+ forkIO :: m a -> m C.ThreadId++instance ForkableMonad IO where+ forkIO act = C.forkIO (act >> return ())++instance (ForkableMonad m) => ForkableMonad (ReaderT r m) where+ forkIO act = do+ env <- ask+ lift $ forkIO (runReaderT act env)++instance (ForkableMonad m) => ForkableMonad (StateT s m) where+ forkIO act = do+ st <- get+ lift $ forkIO (runStateT act st)