Added Haddock documentation. Converted the existing module documentation to Haddock...
authorAndriy Palamarchuk <apa3a@yahoo.com>
Mon, 4 Jun 2007 13:36:02 +0000 (13:36 +0000)
committerAndriy Palamarchuk <apa3a@yahoo.com>
Mon, 4 Jun 2007 13:36:02 +0000 (13:36 +0000)
Control/Monad/Cont.hs
Control/Monad/Cont/Class.hs

index 1152e89..5937867 100644 (file)
@@ -1,19 +1,55 @@
 {-# OPTIONS -fallow-undecidable-instances #-}
 -- Search for -fallow-undecidable-instances to see why this is needed
 
------------------------------------------------------------------------------
--- |
--- Module      :  Control.Monad.Cont
--- Copyright   :  (c) The University of Glasgow 2001
--- License     :  BSD-style (see the file libraries/base/LICENSE)
---
--- Maintainer  :  libraries@haskell.org
--- Stability   :  experimental
--- Portability :  non-portable (multi-parameter type classes)
---
--- Continuation monads.
---
------------------------------------------------------------------------------
+{- |
+Module      :  Control.Monad.Cont
+Copyright   :  (c) The University of Glasgow 2001,
+               (c) Jeff Newbern 2003-2007,
+               (c) Andriy Palamarchuk 2007
+License     :  BSD-style (see the file libraries/base/LICENSE)
+
+Maintainer  :  libraries@haskell.org
+Stability   :  experimental
+Portability :  non-portable (multi-parameter type classes)
+
+[Computation type:] Computations which can be interrupted and resumed.
+
+[Binding strategy:] Binding a function to a monadic value creates
+a new continuation which uses the function as the continuation of the monadic
+computation.
+
+[Useful for:] Complex control structures, error handling,
+and creating co-routines.
+
+[Zero and plus:] None.
+
+[Example type:] @'Cont' r a@
+
+The Continuation monad represents computations in continuation-passing style
+(CPS).
+In continuation-passing style function result is not returned,
+but instead is passed to another function,
+received as a parameter (continuation).
+Computations are built up from sequences
+of nested continuations, terminated by a final continuation (often @id@)
+which produces the final result.
+Since continuations are functions which represent the future of a computation,
+manipulation of the continuation functions can achieve complex manipulations
+of the future of the computation,
+such as interrupting a computation in the middle, aborting a portion
+of a computation, restarting a computation, and interleaving execution of
+computations.
+The Continuation monad adapts CPS to the structure of a monad.
+
+Before using the Continuation monad, be sure that you have
+a firm understanding of continuation-passing style
+and that continuations represent the best solution to your particular
+design problem.
+Many algorithms which require continuations in other languages do not require
+them in Haskell, due to Haskell's lazy semantics.
+Abuse of the Continuation monad can produce code that is impossible
+to understand and maintain.
+-}
 
 module Control.Monad.Cont (
     module Control.Monad.Cont.Class,
@@ -25,6 +61,14 @@ module Control.Monad.Cont (
     withContT,
     module Control.Monad,
     module Control.Monad.Trans,
+    -- * Example 1: Simple Continuation Usage
+    -- $simpleContExample
+
+    -- * Example 2: Using @callCC@
+    -- $callCCExample
+    
+    -- * Example 3: Using @ContT@ Monad Transformer
+    -- $ContTExample
   ) where
 
 import Control.Monad
@@ -33,10 +77,27 @@ import Control.Monad.Reader.Class
 import Control.Monad.State.Class
 import Control.Monad.Trans
 
--- ---------------------------------------------------------------------------
--- Our parameterizable continuation monad
+{- |
+Continuation monad.
+@Cont r a@ is a CPS computation that produces an intermediate result
+of type @a@ within a CPS computation whose final result type is @r@.
+
+The @return@ function simply creates a continuation which passes the value on.
+
+The @>>=@ operator adds the bound function into the continuation chain.
+-}
+newtype Cont r a = Cont {
+
+    {- | Runs a CPS computation, returns its result after applying
+    the final continuation to it.
+    Parameters:
 
-newtype Cont r a = Cont { runCont :: (a -> r) -> r }
+    * a continuation computation (@Cont@).
+
+    * the final continuation, which produces the final result (often @id@).
+    -}
+    runCont :: (a -> r) -> r
+}
 
 mapCont :: (r -> r) -> Cont r a -> Cont r a
 mapCont f m = Cont $ f . runCont m
@@ -54,9 +115,10 @@ instance Monad (Cont r) where
 instance MonadCont (Cont r) where
     callCC f = Cont $ \c -> runCont (f (\a -> Cont $ \_ -> c a)) c
 
--- ---------------------------------------------------------------------------
--- Our parameterizable continuation monad, with an inner monad
-
+{- |
+The continuation monad transformer.
+Can be used to add continuation handling to other monads.
+-}
 newtype ContT r m a = ContT { runContT :: (a -> m r) -> m r }
 
 mapContT :: (m r -> m r) -> ContT r m a -> ContT r m a
@@ -96,3 +158,89 @@ instance (MonadState s m) => MonadState s (ContT r m) where
     get = lift get
     put = lift . put
 
+{- $simpleContExample
+Calculating length of a list continuation-style:
+
+>calculateLength :: [a] -> Cont r Int
+>calculateLength l = return (length l)
+
+Here we use @calculateLength@ by making it to pass its result to @print@:
+
+>main = do
+>  runCont (calculateLength "123") print
+>  -- result: 3
+
+It is possible to chain 'Cont' blocks with @>>=@.
+
+>double :: Int -> Cont r Int
+>double n = return (n * 2)
+>
+>main = do
+>  runCont (calculateLength "123" >>= double) print
+>  -- result: 6
+-}
+
+{- $callCCExample
+This example gives a taste of how escape continuations work, shows a typical
+pattern for their usage.
+
+>-- Returns a string depending on the length of the name parameter.
+>-- If the provided string is empty, returns an error.
+>-- Otherwise, returns a welcome message.
+>whatsYourName :: String -> String
+>whatsYourName name =
+>  (`runCont` id) $ do                      -- 1
+>    response <- callCC $ \exit -> do       -- 2
+>      validateName name exit               -- 3
+>      return $ "Welcome, " ++ name ++ "!"  -- 4
+>    return response                        -- 5
+>
+>validateName name exit = do
+>  when (null name) (exit "You forgot to tell me your name!")
+
+Here is what this example does:
+
+(1) Runs an anonymous 'Cont' block and extracts value from it with
+@(\`runCont\` id)@. Here @id@ is the continuation, passed to the @Cont@ block.
+
+(1) Binds @response@ to the result of the following 'callCC' block,
+binds @exit@ to the continuation.
+
+(1) Validates @name@.
+This approach illustrates advantage of using 'callCC' over @return@.
+We pass the continuation to @validateName@,
+and interrupt execution of the @Cont@ block from /inside/ of @validateName@.
+
+(1) Returns the welcome message from the @callCC@ block.
+This line is not executed if @validateName@ fails.
+
+(1) Returns from the @Cont@ block.
+-}
+
+{-$ContTExample
+'ContT' can be used to add continuation handling to other monads.
+Here is an example how to combine it with @IO@ monad:
+
+>import Control.Monad.Cont
+>import System.IO
+>
+>main = do
+>  hSetBuffering stdout NoBuffering
+>  runContT (callCC askString) reportResult
+>
+>askString :: (String -> ContT () IO String) -> ContT () IO String
+>askString next = do
+>  liftIO $ putStrLn "Please enter a string"
+>  s <- liftIO $ getLine
+>  next s
+>
+>reportResult :: String -> IO ()
+>reportResult s = do
+>  putStrLn ("You entered: " ++ s)
+
+Action @askString@ requests user to enter a string,
+and passes it to the continuation.
+@askString@ takes as a parameter a continuation taking a string parameter,
+and returning @IO ()@.
+Compare its signature to 'runContT' definition.
+-}
index b8787d5..2882685 100644 (file)
@@ -1,24 +1,78 @@
 {-# OPTIONS -fallow-undecidable-instances #-}
 -- Search for -fallow-undecidable-instances to see why this is needed
 
------------------------------------------------------------------------------
--- |
--- Module      :  Control.Monad.Cont.Class
--- Copyright   :  (c) The University of Glasgow 2001
--- License     :  BSD-style (see the file libraries/base/LICENSE)
---
--- Maintainer  :  libraries@haskell.org
--- Stability   :  experimental
--- Portability :  non-portable (multi-parameter type classes)
---
--- Continuation monad class
---
------------------------------------------------------------------------------
+{- |
+Module      :  Control.Monad.Cont.Class
+Copyright   :  (c) The University of Glasgow 2001,
+               (c) Jeff Newbern 2003-2007,
+               (c) Andriy Palamarchuk 2007
+License     :  BSD-style (see the file libraries/base/LICENSE)
+
+Maintainer  :  libraries@haskell.org
+Stability   :  experimental
+Portability :  non-portable (multi-parameter type classes)
+
+[Computation type:] Computations which can be interrupted and resumed.
+
+[Binding strategy:] Binding a function to a monadic value creates
+a new continuation which uses the function as the continuation of the monadic
+computation.
+
+[Useful for:] Complex control structures, error handling,
+and creating co-routines.
+
+[Zero and plus:] None.
+
+[Example type:] @'Cont' r a@
+
+The Continuation monad represents computations in continuation-passing style
+(CPS).
+In continuation-passing style function result is not returned,
+but instead is passed to another function,
+received as a parameter (continuation).
+Computations are built up from sequences
+of nested continuations, terminated by a final continuation (often @id@)
+which produces the final result.
+Since continuations are functions which represent the future of a computation,
+manipulation of the continuation functions can achieve complex manipulations
+of the future of the computation,
+such as interrupting a computation in the middle, aborting a portion
+of a computation, restarting a computation, and interleaving execution of
+computations.
+The Continuation monad adapts CPS to the structure of a monad.
+
+Before using the Continuation monad, be sure that you have
+a firm understanding of continuation-passing style
+and that continuations represent the best solution to your particular
+design problem.
+Many algorithms which require continuations in other languages do not require
+them in Haskell, due to Haskell's lazy semantics.
+Abuse of the Continuation monad can produce code that is impossible
+to understand and maintain.
+-}
 
 module Control.Monad.Cont.Class (
     MonadCont(..),
   ) where
 
 class (Monad m) => MonadCont m where
+    {- | @callCC@ (call-with-current-continuation)
+    calls a function with the current continuation as its argument.
+    Provides an escape continuation mechanism for use with Continuation monads.
+    Escape continuations allow to abort the current computation and return
+    a value immediately.
+    They achieve a similar effect to 'Control.Monad.Error.throwError'
+    and 'Control.Monad.Error.catchError'
+    within an 'Control.Monad.Error.Error' monad.
+    Advantage of this function over calling @return@ is that it makes
+    the continuation explicit,
+    allowing more flexibility and better control
+    (see examples in "Control.Monad.Cont").
+
+    The standard idiom used with @callCC@ is to provide a lambda-expression
+    to name the continuation. Then calling the named continuation anywhere
+    within its scope will escape from the computation,
+    even if it is many layers deep within nested computations.
+    -}
     callCC :: ((a -> m b) -> m a) -> m a