[project @ 2003-11-10 15:54:55 by sof]
authorsof <unknown>
Mon, 10 Nov 2003 15:54:55 +0000 (15:54 +0000)
committersof <unknown>
Mon, 10 Nov 2003 15:54:55 +0000 (15:54 +0000)
brought into the hier-lib world; stripped away outdated code & comments

Control/Parallel/Strategies.hs

index 03932b1..9ef4968 100644 (file)
 -- Parallel strategy combinators
 --
 -----------------------------------------------------------------------------
+module Control.Parallel.Strategies where
 
-{-
-Time-stamp: <Wed Mar 21 2001 00:45:34 Stardate: [-30]6360.15 hwloidl>
-$Id: Strategies.hs,v 1.4 2002/05/09 13:16:30 simonmar Exp $
-
-This module defines parallel strategy combinators
-
-       Phil Trinder, Hans-Wolfgang Loidl, Kevin Hammond et al. 
-
-       Based on Version VII (1/5/96) `Strategies96' of type a -> ()
-
-Author:    $Author: simonmar $
-Date:      $Date: 2002/05/09 13:16:30 $
-Revision:  $Revision: 1.4 $
-Source:    $Source: /srv/cvs/cvs.haskell.org/fptools/libraries/base/Control/Parallel/Strategies.hs,v $
-State:     $State: Exp $
-
-This module defines evaluation strategies for controlling the parallel
-evaluation of non-strict programs. They provide a clean separation between
-algorithmic and behavioural code.
+-- based on hslibs/concurrent/Strategies.lhs; see it for more detailed
+-- code comments. Original authors:
+--
+--     Phil Trinder, Hans-Wolfgang Loidl, Kevin Hammond et al. 
+--
+import Control.Parallel as Parallel
+import Data.Ix
+import Data.Array
+import Data.Complex
+import Data.Ratio
 
-The functions described here, and their use is documented in
+-- not a terribly portable way of getting at Ratio rep.
+#ifdef __GLASGOW_HASKELL__
+import GHC.Real        (Ratio(..))     -- The basic defns for Ratio
+#endif
 
-"Algorithm + Strategy = Parallelism", 
-P.W. Trinder, K. Hammond, H-W. Loidl, S.L. Peyton Jones 
-In Journal of Functional Programming 8(1):23--60, January 1998.
-URL: http://www.cee.hw.ac.uk/~dsg/gph/papers/ps/strategies.ps.gz
+#ifdef __HUGS__
+import Hugs.Prelude(Ratio(..) )
+#endif
 
-This module supports Haskell 1.2, Haskell 1.4 and Haskell98.
-The distinction is made based on the __HASKELL1__ CPP variable. 
-Parts of the module could be rewritten using constructor classes.
+#ifdef __NHC__
+import Ratio (Ratio(..) )
+#endif
 
------------------------------------------------------------------------------
-The history of the Strategies module:
-
-Changelog:
-$Log: Strategies.hs,v $
-Revision 1.4  2002/05/09 13:16:30  simonmar
-Rename libraries/core to libraries/base in the module headers.
-
-Revision 1.3  2002/04/26 13:34:06  simonmar
-Remove \$Id\$ from all files: it isn't particularly useful (see
-previous discussion on cvs-ghc@haskell.org), and it confuses Haddock.
-
-Revision 1.2  2002/04/24 16:31:39  simonmar
-Add the single character '|' to the header comment of each module so
-that Haddock will parse it as the module documentation.
-
-Revision 1.1  2001/06/28 14:15:02  simonmar
-First cut of the Haskell Core Libraries
-=======================================
-
-NOTE: it's not meant to be a working snapshot.  The code is just here
-to look at and so the NHC/Hugs guys can start playing around with it.
-
-There is no build system.  For GHC, the libraries tree is intended to
-be grafted onto an existing fptools/ tree, and the Makefile in
-libraries/base is a quick hack for that setup.  This won't work at the
-moment without the other changes needed in fptools/ghc, which I
-haven't committed because they'll cause breakage.  However, with the
-changes required these sources build a working Prelude and libraries.
-
-The layout mostly follows the one we agreed on, with one or two minor
-changes; in particular the Data/Array layout probably isn't final
-(there are several choices here).
-
-The document is in libraries/base/doc as promised.
-
-The cbits stuff is just a copy of ghc/lib/std/cbits and has
-GHC-specific stuff in it.  We should really separate the
-compiler-specific C support from any compiler-independent C support
-there might be.
-
-Don't pay too much attention to the portability or stability status
-indicated in the header of each source file at the moment - I haven't
-gone through to make sure they're all consistent and make sense.
-
-I'm using non-literate source outside of GHC/.  Hope that's ok with
-everyone.
-
-We need to discuss how the build system is going to work...
-
-Revision 1.3  2001/03/22 03:51:12  hwloidl
-                                                  -*- outline -*-
-Time-stamp: <Thu Mar 22 2001 03:50:16 Stardate: [-30]6365.79 hwloidl>
-
-This commit covers changes in GHC to get GUM (way=mp) and GUM/GdH (way=md)
-working. It is a merge of my working version of GUM, based on GHC 4.06,
-with GHC 4.11. Almost all changes are in the RTS (see below).
-
-GUM is reasonably stable, we used the 4.06 version in large-ish programs for
-recent papers. Couple of things I want to change, but nothing urgent.
-GUM/GdH has just been merged and needs more testing. Hope to do that in the
-next weeks. It works in our working build but needs tweaking to run.
-GranSim doesn't work yet (*sigh*). Most of the code should be in, but needs
-more debugging.
-
-ToDo: I still want to make the following minor modifications before the release
-- Better wrapper skript for parallel execution [ghc/compiler/main]
-- Update parallel docu: started on it but it's minimal [ghc/docs/users_guide]
-- Clean up [nofib/parallel]: it's a real mess right now (*sigh*)
-- Update visualisation tools (minor things only IIRC) [ghc/utils/parallel]
-- Add a Klingon-English glossary
-
-* RTS:
-
-Almost all changes are restricted to ghc/rts/parallel and should not
-interfere with the rest. I only comment on changes outside the parallel
-dir:
-
-- Several changes in Schedule.c (scheduling loop; createThreads etc);
-  should only affect parallel code
-- Added ghc/rts/hooks/ShutdownEachPEHook.c
-- ghc/rts/Linker.[ch]: GUM doesn't know about Stable Names (ifdefs)!!
-- StgMiscClosures.h: END_TSO_QUEUE etc now defined here (from StgMiscClosures.hc)
-                     END_ECAF_LIST was missing a leading stg_
-- SchedAPI.h: taskStart now defined in here; it's only a wrapper around
-              scheduleThread now, but might use some init, shutdown later
-- RtsAPI.h: I have nuked the def of rts_evalNothing
-
-* Compiler:
-
-- ghc/compiler/main/DriverState.hs
-  added PVM-ish flags to the parallel way
-  added new ways for parallel ticky profiling and distributed exec
-
-- ghc/compiler/main/DriverPipeline.hs
-  added a fct run_phase_MoveBinary which is called with way=mp after linking;
-  it moves the bin file into a PVM dir and produces a wrapper script for
-  parallel execution
-  maybe cleaner to add a MoveBinary phase in DriverPhases.hs but this way
-  it's less intrusive and MoveBinary makes probably only sense for mp anyway
-
-* Nofib:
-
-- nofib/spectral/Makefile, nofib/real/Makefile, ghc/tests/programs/Makefile:
-  modified to skip some tests if HWL_NOFIB_HACK is set; only tmp to record
-  which test prgs cause problems in my working build right now
-
-Revision 1.2  2000/11/18 02:13:11  hwloidl
-Now provides explicit def of seq (rather than just re-exporting).
-Required by the current version of the compiler.
-
-Revision 1.1  2000/01/14 13:34:32  hwloidl
-Module for specifying (parallel) behavioural code.
-
-Revision 1.9  1997/10/01 00:27:19  hwloidl
-Type of par and seq changed to Done -> Done -> Done with Done = ()
-Works for Haskell 1.2 as well as Haskell 1.4 (checks the CPP variable
-__HASKELL1__ to distinguish setups).
-Fixed precedences for par and seq for Haskell 1.4 (stronger than using).
-New infix operators >| and >|| as aliases for par and seq as strategy
-combinators.
-
-Revision 1.8  1997/05/20 21:13:22  hwloidl
-Revised to use `demanding` and `sparking` (final JFP paper version)
-
-Revision 1.7  1997/04/02 21:26:21  hwloidl
-Minor changes in documentation, none in the code.
-
-
-revision 1.5
-Version VII.1; Strategies96; Type: a -> ()
-Minor changes to previous version.
-CPP flags now separate GUM from GranSim version.
-Infix declaration for `using` (important for e.g. quicksort where the old
-version puts parentheses in the wrong way).
-Moer instances for NFData and markStartegies (in GranSim setup only).
-
-revision 1.4
-Version VII; Strategies96; Type: a -> ()
-The type has changed again; with the old type it's not possible to describe
-all the strategies we want (for example seqPair r0 rnf which should not
-evaluate the first component of the pair at all). The () type acts as info
-that the strategy has been applied.
-The function `using` is used as inverse strategy application i.e.
-on top level we usually have something like res `using` strat where ...
-The markStrategy hack is included in this version: it attaches an Int value
-to the currently running strategy (this can be inherited by all sub-strats)
-It doesn't model the jumps between evaluating producer and consumer properly
-(for that something like cost centers would be necessary).
-
-revision 1.3
-Version VI (V-based); Strategies95; Type: a -> a
-Now uses library modules like FiniteMap with strategies in there.
-CPP flags for using the same module with GUM and GranSim.
-A few new strategies.
-
-revision 1.2
-Version V; Strategies95; Type: a -> a
-The type of Strategies has changed from a -> () to a -> a
-All strategies and instances of NFData have been redefined accordingly.
-This branch started off after discussions between PWT, SLPJ and HWL in
-mid Nov (start of development of the actual module: 10/1/96)
-
-revision 1.1 Initial revision
------------------------------------------------------------------------------
--- To use fakeinfo first replace all %%$ by \@ 
--- If you have fakeinfo makers in the file you need a slightly modified 
--- version of the lit-deatify script (called by lit2pgm). You get that 
--- version on Suns and Alphas in Glasgow by using 
---  \tr{lit2pgm -H "${HOME}/bin/`hw_os`"}
--- in your Makefile
------------------------------------------------------------------------------
+infixl 0 `using`,`demanding`,`sparking`              -- weakest precedence!
 
---@node Evaluation Strategies, , ,
---@chapter Evaluation Strategies
-
---@menu
---* Imports and infix declarations::  
---* Strategy Type and Application::  
---* Basic Strategies::         
---* Strategic Function Application::  
---* Marking a Strategy::       
---* Strategy Instances::       
---* Lolita-specific Strategies::  
---@end menu
-
---@node Imports and infix declarations, Strategy Type and Application, Evaluation Strategies, Evaluation Strategies
---@section Imports and infix declarations
-
-> module Strategies(
->#if (__HASKELL1__>=4)
->                   module Strategies,
->                   module Parallel
->#else
->                   Strategies..
->#endif
->                  ) where
->
->#if defined(GRAN) && !(__HASKELL1__>=4)
-> import PreludeGlaST                        -- only needed for markStrat
->#endif
->#if (__HASKELL1__>=4)
-
-<> import Prelude hiding (seq)
-<> import qualified Parallel
-
-> import Parallel
-
->#else
-> import Parallel renaming (par to par_from_Parallel, seq to seq_from_Parallel)
->#endif
-
->#if (__HASKELL1__>=4)
-> import Ix
-> import Array
->#endif
-
->#if defined(PAR_GRAN_LIST)
-> import QSort -- tmp (only for parGranList)
->#endif
-
-I lifted the precedence of @par@ and @seq@ by one level to make @using@ the 
-combinator with the weakest precedence.
-Oooops, there seems to be a bug in ghc 0.29 prohibiting another infix 
-declaration of @par@ and @seq@ despite renaming the imported versions.
-
->#if (__HASKELL1__>=4)
-
-<> infixr 2 `par`           -- was: 0
-<> infixr 3 `seq`           -- was: 1 
-
->#else
-> infixr 0 `par`           -- was: 0
-> infixr 1 `seq`           -- was: 1 
->#endif
-
-> infixl 0 `using`,`demanding`,`sparking`              -- weakest precedence!
-
-> infixr 2 >||                -- another name for par
-> infixr 3 >|                 -- another name for seq
-> infixl 6 $||, $|            -- strategic function application (seq and par)
-> infixl 9 .|, .||, -|, -||   -- strategic (inverse) function composition
-
-> strategy_version = "$Revision: 1.4 $"
-> strategy_id = "$Id: Strategies.hs,v 1.4 2002/05/09 13:16:30 simonmar Exp $"
+infixr 2 >||                -- another name for par
+infixr 3 >|                 -- another name for seq
+infixl 6 $||, $|            -- strategic function application (seq and par)
+infixl 9 .|, .||, -|, -||   -- strategic (inverse) function composition
 
 ------------------------------------------------------------------------------
-                       Strategy Type, Application and Semantics              
+--                     Strategy Type, Application and Semantics              
 ------------------------------------------------------------------------------
---@node Strategy Type and Application, Basic Strategies, Imports and infix declarations, Evaluation Strategies
---@section Strategy Type and Application
-
---@cindex Strategy
-
-> type Done = ()
-> type Strategy a = a -> Done
+type Done = ()
+type Strategy a = a -> Done
 
+{-
 A strategy takes a value and returns a dummy `done' value to indicate that
 the specifed evaluation has been performed.
 
@@ -313,46 +64,23 @@ The infix fcts >| and >|| are alternative names for `seq` and `par`.
 With the introduction of a Prelude function `seq` separating the Prelude 
 function from the Strategy function becomes a pain. The notation also matches
 the notation for strategic function application.
+-}
 
---@cindex par
---@cindex seq
---@cindex >|
---@cindex >||
-
->#if (__HASKELL1__>=4)
-
+{-
 par and seq have the same types as before; >| and >|| are more specific
 and can only be used when composing strategies.
+-}
+
+(>|), (>||) :: Done -> Done -> Done 
+{-# INLINE (>|) #-}
+{-# INLINE (>||) #-}
+(>|) = Prelude.seq
+(>||) = Parallel.par
 
-<> par :: Done -> Done -> Done 
-<> par = Parallel.par
-<> seq :: a -> b -> b      -- that's the real type of seq defined in Prelude
-<> seq = Parallel.seq
-
-> (>|), (>||) :: Done -> Done -> Done 
-> {-# INLINE (>|) #-}
-> {-# INLINE (>||) #-}
-> (>|) = Prelude.seq
-> (>||) = Parallel.par
->#else
-> par, seq, (>|), (>||) :: Done -> Done -> Done 
-> par = par_from_Parallel
-> seq = seq_from_Parallel
-> {-# INLINE (>|) #-}
-> {-# INLINE (>||) #-}
-> (>|) = seq
-> (>||) = par
->#endif
-
---@cindex using
-
-> using :: a -> Strategy a -> a
->#if (__HASKELL1__>=4)
-> using x s = s x `seq` x
->#else
-> using x s = s x `seq_from_Parallel` x
->#endif
+using :: a -> Strategy a -> a
+using x s = s x `seq` x
 
+{-
 using takes a strategy and a value, and applies the strategy to the
 value before returning the value. Used to express data-oriented parallelism
 
@@ -366,85 +94,56 @@ demanding and sparking are used to express control-oriented
 parallelism. Their second argument is usually a sequence of strategy
 applications combined `par` and `seq`. Sparking should only be used
 with a singleton sequence as it is not necessarily excuted
+-}
 
---@cindex demanding
---@cindex sparking
-
-> demanding, sparking :: a -> Done -> a
->#if (__HASKELL1__>=4)
-> demanding = flip Parallel.seq
-> sparking  = flip Parallel.par
->#else
-> demanding = flip seq_from_Parallel
-> sparking  = flip par_from_Parallel
->#endif
+demanding, sparking :: a -> Done -> a
+demanding = flip Parallel.seq
+sparking  = flip Parallel.par
 
+{-
 sPar and sSeq have been superceded by sparking and demanding: replace 
   e `using` sPar x     with    e `sparking`  x 
   e `using` sSeq x     with    e `demanding` x
 
-<sPar is a strategy corresponding to par. i.e. x `par` e <=> e `using` sPar x
-<
-<> sPar :: a -> Strategy b
-<> sPar x y = x `par` ()
-<
-<sSeq is a strategy corresponding to seq. i.e. x `seq` e <=> e `using` sSeq x
-<
-<> sSeq :: a -> Strategy b
-<> sSeq x y = x `seq` ()
+sPar is a strategy corresponding to par. i.e. x `par` e <=> e `using` sPar x
+-}
+
+sPar :: a -> Strategy b
+sPar x y = x `par` ()
+
+{-
+sSeq is a strategy corresponding to seq. i.e. x `seq` e <=> e `using` sSeq x
+-}
+sSeq :: a -> Strategy b
+sSeq x y = x `seq` ()
 
 -----------------------------------------------------------------------------
-                       Basic Strategies                                     
+--                     Basic Strategies                                     
 -----------------------------------------------------------------------------
---@node Basic Strategies, Strategic Function Application, Strategy Type and Application, Evaluation Strategies
---@section Basic Strategies
-
-r0 performs *no* evaluation on its argument.
-
---@cindex r0
-
-> r0 :: Strategy a 
-> r0 x = ()
-
-rwhnf reduces its argument to weak head normal form.
-
---@cindex rwhnf
---@cindex rnf
---@cindex NFData
-
->#if defined(__HASKELL98__)
-> rwhnf :: Strategy a 
-> rwhnf x = x `seq` ()  
->#elif (__HASKELL1__==4)
-> rwhnf :: Eval a => Strategy a 
-> rwhnf x = x `seq` ()  
->#else
-> rwhnf :: Strategy a 
-> rwhnf x = x `seq_from_Parallel` ()  
->#endif
-
->#if defined(__HASKELL98__)
-> class NFData a where
->#elif (__HASKELL1__>=4)
-> class Eval a => NFData a where
->#else
-> class NFData a where
->#endif
->   -- rnf reduces its argument to (head) normal form
->   rnf :: Strategy a
->   -- Default method. Useful for base types. A specific method is necessay for
->   -- constructed types
->   rnf = rwhnf
->
-> class (NFData a, Integral a) => NFDataIntegral a
-> class (NFData a, Ord a) => NFDataOrd a
+
+-- r0 performs *no* evaluation on its argument.
+r0 :: Strategy a 
+r0 x = ()
+
+--rwhnf reduces its argument to weak head normal form.
+rwhnf :: Strategy a 
+rwhnf x = x `seq` ()  
+
+class NFData a where
+  -- rnf reduces its argument to (head) normal form
+  rnf :: Strategy a
+  -- Default method. Useful for base types. A specific method is necessay for
+  -- constructed types
+  rnf = rwhnf
+
+class (NFData a, Integral a) => NFDataIntegral a
+class (NFData a, Ord a) => NFDataOrd a
 
 ------------------------------------------------------------------------------
-                        Strategic Function Application
+--                      Strategic Function Application
 ------------------------------------------------------------------------------
---@node Strategic Function Application, Marking a Strategy, Basic Strategies, Evaluation Strategies
---@section Strategic Function Application
 
+{-
 The two  infix functions @$|@   and @$||@  perform sequential and  parallel
 function application, respectively. They  are parameterised with a strategy
 that is applied to the argument of the  function application.  This is very
@@ -452,46 +151,37 @@ handy when  writing  pipeline parallelism  as  a sequence of  @$@, @$|@ and
 @$||@'s. There is no  need of naming intermediate values  in this case. The
 separation  of algorithm from strategy  is  achieved by allowing strategies
 only as second arguments to @$|@ and @$||@.
+-}
 
---@cindex $|
---@cindex $||
-
-> ($|), ($||) :: (a -> b) -> Strategy a -> a -> b
-
-<> f $| s  = \ x -> f x `using` \ _ -> s x `seq` ()
-<> f $|| s = \ x -> f x `using` \ _ -> s x `par` ()
+($|), ($||) :: (a -> b) -> Strategy a -> a -> b
 
-f $| s  = \ x -> f x `demanding` s x
-f $|| s = \ x -> f x `sparking`  s x
+f $| s  = \ x -> f x `demanding` s x
+f $|| s = \ x -> f x `sparking`  s x
 
+{-
 The same thing for function composition (.| and .||) and inverse function
 composition (-| and -||) for those who read their programs from left to 
 right.
+-}
 
---@cindex .|
---@cindex .||
---@cindex -|
---@cindex -||
-
-> (.|), (.||) :: (b -> c) -> Strategy b -> (a -> b) -> (a -> c)
-> (-|), (-||) :: (a -> b) -> Strategy b -> (b -> c) -> (a -> c)
+(.|), (.||) :: (b -> c) -> Strategy b -> (a -> b) -> (a -> c)
+(-|), (-||) :: (a -> b) -> Strategy b -> (b -> c) -> (a -> c)
 
-(.|) f s g = \ x -> let  gx = g x 
-                    in   f gx `demanding` s gx
-(.||) f s g = \ x -> let  gx = g x 
-                     in   f gx `sparking` s gx
+(.|) f s g = \ x -> let  gx = g x 
+                    in   f gx `demanding` s gx
+(.||) f s g = \ x -> let  gx = g x 
+                     in   f gx `sparking` s gx
 
-(-|) f s g = \ x -> let  fx = f x 
-                    in   g fx `demanding` s fx
-(-||) f s g = \ x -> let  fx = f x 
-                     in   g fx `sparking` s fx 
+(-|) f s g = \ x -> let  fx = f x 
+                    in   g fx `demanding` s fx
+(-||) f s g = \ x -> let  fx = f x 
+                     in   g fx `sparking` s fx 
 
 ------------------------------------------------------------------------------
-                       Marking a Strategy
+--                     Marking a Strategy
 ------------------------------------------------------------------------------
---@node Marking a Strategy, Strategy Instances, Strategic Function Application, Evaluation Strategies
---@section Marking a Strategy
 
+{-
 Marking a strategy.
 
 Actually, @markStrat@  sticks a label @n@  into the sparkname  field of the
@@ -501,473 +191,293 @@ all its children have  the sparkname @n@ (if the  static sparkname field in
 the @parGlobal@ annotation contains the value 1). Note, that the @SN@ field
 of starting the marked strategy itself contains the sparkname of the parent
 thread. The END event contains @n@ as sparkname.
+-}
 
---@cindex markStrat
-
->#if defined(GRAN) && !(__HASKELL1__>=4)
-> markStrat :: Int -> Strategy a -> Strategy a 
-> markStrat n s x = unsafePerformPrimIO (
->      _casm_ ``%r = set_sparkname(CurrentTSO, %0);'' n `thenPrimIO` \ z ->
->      returnPrimIO (s x))
->#endif
+#if 0
+markStrat :: Int -> Strategy a -> Strategy a 
+markStrat n s x = unsafePerformPrimIO (
+     _casm_ ``%r = set_sparkname(CurrentTSO, %0);'' n `thenPrimIO` \ z ->
+     returnPrimIO (s x))
+#endif
 
 -----------------------------------------------------------------------------
-                       Strategy Instances and Functions                     
+--                     Strategy Instances and Functions                     
 -----------------------------------------------------------------------------
---@node Strategy Instances, Lolita-specific Strategies, Marking a Strategy, Evaluation Strategies
---@section Strategy Instances
+
 -----------------------------------------------------------------------------
-                       Tuples
+--                     Tuples
 -----------------------------------------------------------------------------
---@menu
---* Tuples::                   
---* Numbers::                  
---* Characters::               
---* Booleans::                 
---* Unit::                     
---* Lists::                    
---* Arrays::                   
---@end menu
-
---@node Tuples, Numbers, Strategy Instances, Strategy Instances
---@subsection Tuples
 
+{-
 We currently support up to 9-tuples. If you need longer tuples you have to 
 add the instance explicitly to your program.
+-}
+
+instance (NFData a, NFData b) => NFData (a,b) where
+  rnf (x,y) = rnf x `seq` rnf y
+
+instance (NFData a, NFData b, NFData c) => NFData (a,b,c) where
+  rnf (x,y,z) = rnf x `seq` rnf y `seq` rnf z 
+
+instance (NFData a, NFData b, NFData c, NFData d) => NFData (a,b,c,d) where
+  rnf (x1,x2,x3,x4) = rnf x1 `seq` 
+                       rnf x2 `seq` 
+                       rnf x3 `seq` 
+                       rnf x4 
+
+instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5) => 
+         NFData (a1, a2, a3, a4, a5) where
+  rnf (x1, x2, x3, x4, x5) =
+                  rnf x1 `seq`
+                  rnf x2 `seq`
+                  rnf x3 `seq`
+                  rnf x4 `seq`
+                  rnf x5
+
+instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6) => 
+         NFData (a1, a2, a3, a4, a5, a6) where
+  rnf (x1, x2, x3, x4, x5, x6) =
+                  rnf x1 `seq`
+                  rnf x2 `seq`
+                  rnf x3 `seq`
+                  rnf x4 `seq`
+                  rnf x5 `seq`
+                  rnf x6
+
+instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6, NFData a7) => 
+         NFData (a1, a2, a3, a4, a5, a6, a7) where
+  rnf (x1, x2, x3, x4, x5, x6, x7) =
+                  rnf x1 `seq`
+                  rnf x2 `seq`
+                  rnf x3 `seq`
+                  rnf x4 `seq`
+                  rnf x5 `seq`
+                  rnf x6 `seq`
+                  rnf x7
+
+instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6, NFData a7, NFData a8) => 
+         NFData (a1, a2, a3, a4, a5, a6, a7, a8) where
+  rnf (x1, x2, x3, x4, x5, x6, x7, x8) =
+                  rnf x1 `seq`
+                  rnf x2 `seq`
+                  rnf x3 `seq`
+                  rnf x4 `seq`
+                  rnf x5 `seq`
+                  rnf x6 `seq`
+                  rnf x7 `seq`
+                  rnf x8
+
+instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6, NFData a7, NFData a8, NFData a9) => 
+         NFData (a1, a2, a3, a4, a5, a6, a7, a8, a9) where
+  rnf (x1, x2, x3, x4, x5, x6, x7, x8, x9) =
+                  rnf x1 `seq`
+                  rnf x2 `seq`
+                  rnf x3 `seq`
+                  rnf x4 `seq`
+                  rnf x5 `seq`
+                  rnf x6 `seq`
+                  rnf x7 `seq`
+                  rnf x8 `seq`
+                  rnf x9
+
+
+seqPair :: Strategy a -> Strategy b -> Strategy (a,b)
+seqPair strata stratb (x,y) = strata x `seq` stratb y 
+
+parPair :: Strategy a -> Strategy b -> Strategy (a,b)
+parPair strata stratb (x,y) = strata x `par` stratb y `par` ()
 
-> instance (NFData a, NFData b) => NFData (a,b) where
->   rnf (x,y) = rnf x `seq` rnf y
-
-> instance (NFData a, NFData b, NFData c) => NFData (a,b,c) where
->   rnf (x,y,z) = rnf x `seq` rnf y `seq` rnf z 
-
-> instance (NFData a, NFData b, NFData c, NFData d) => NFData (a,b,c,d) where
->   rnf (x1,x2,x3,x4) = rnf x1 `seq` 
->                      rnf x2 `seq` 
->                      rnf x3 `seq` 
->                      rnf x4 
-
-> -- code automatically inserted by `hwl-insert-NFData-n-tuple'
-> instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5) => 
->          NFData (a1, a2, a3, a4, a5) where
->   rnf (x1, x2, x3, x4, x5) =
->                   rnf x1 `seq`
->                   rnf x2 `seq`
->                   rnf x3 `seq`
->                   rnf x4 `seq`
->                   rnf x5
-
-> -- code automatically inserted by `hwl-insert-NFData-n-tuple'
-> instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6) => 
->          NFData (a1, a2, a3, a4, a5, a6) where
->   rnf (x1, x2, x3, x4, x5, x6) =
->                   rnf x1 `seq`
->                   rnf x2 `seq`
->                   rnf x3 `seq`
->                   rnf x4 `seq`
->                   rnf x5 `seq`
->                   rnf x6
-
-> -- code automatically inserted by `hwl-insert-NFData-n-tuple'
-> instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6, NFData a7) => 
->          NFData (a1, a2, a3, a4, a5, a6, a7) where
->   rnf (x1, x2, x3, x4, x5, x6, x7) =
->                   rnf x1 `seq`
->                   rnf x2 `seq`
->                   rnf x3 `seq`
->                   rnf x4 `seq`
->                   rnf x5 `seq`
->                   rnf x6 `seq`
->                   rnf x7
-
-> -- code automatically inserted by `hwl-insert-NFData-n-tuple'
-> instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6, NFData a7, NFData a8) => 
->          NFData (a1, a2, a3, a4, a5, a6, a7, a8) where
->   rnf (x1, x2, x3, x4, x5, x6, x7, x8) =
->                   rnf x1 `seq`
->                   rnf x2 `seq`
->                   rnf x3 `seq`
->                   rnf x4 `seq`
->                   rnf x5 `seq`
->                   rnf x6 `seq`
->                   rnf x7 `seq`
->                   rnf x8
-
-> -- code automatically inserted by `hwl-insert-NFData-n-tuple'
-> instance (NFData a1, NFData a2, NFData a3, NFData a4, NFData a5, NFData a6, NFData a7, NFData a8, NFData a9) => 
->          NFData (a1, a2, a3, a4, a5, a6, a7, a8, a9) where
->   rnf (x1, x2, x3, x4, x5, x6, x7, x8, x9) =
->                   rnf x1 `seq`
->                   rnf x2 `seq`
->                   rnf x3 `seq`
->                   rnf x4 `seq`
->                   rnf x5 `seq`
->                   rnf x6 `seq`
->                   rnf x7 `seq`
->                   rnf x8 `seq`
->                   rnf x9
-
---@cindex seqPair
-
-> seqPair :: Strategy a -> Strategy b -> Strategy (a,b)
-> seqPair strata stratb (x,y) = strata x `seq` stratb y 
-
---@cindex parPair
-
-> parPair :: Strategy a -> Strategy b -> Strategy (a,b)
-> parPair strata stratb (x,y) = strata x `par` stratb y `par` ()
-
+{-
 The reason for the  second `par` is so that the strategy terminates 
 quickly. This is important if the strategy is used as the 1st argument of a seq
+-}
 
---@cindex seqTriple
-
-> seqTriple :: Strategy a -> Strategy b -> Strategy c -> Strategy (a,b,c)
-> seqTriple strata stratb stratc p@(x,y,z) = 
->   strata x `seq` 
->   stratb y `seq`
->   stratc z 
+seqTriple :: Strategy a -> Strategy b -> Strategy c -> Strategy (a,b,c)
+seqTriple strata stratb stratc p@(x,y,z) = 
+  strata x `seq` 
+  stratb y `seq`
+  stratc z 
 
---@cindex parTriple
-
-> parTriple :: Strategy a -> Strategy b -> Strategy c -> Strategy (a,b,c)
-> parTriple strata stratb stratc (x,y,z) = 
->   strata x `par` 
->   stratb y `par` 
->   stratc z `par`
->   ()
-
------------------------------------------------------------------------------
-                       Numbers                                              
------------------------------------------------------------------------------
---@node Numbers, Characters, Tuples, Strategy Instances
---@subsection Numbers
+parTriple :: Strategy a -> Strategy b -> Strategy c -> Strategy (a,b,c)
+parTriple strata stratb stratc (x,y,z) = 
+  strata x `par` 
+  stratb y `par` 
+  stratc z `par`
+  ()
 
+{-
 Weak head normal form and normal form are identical for integers, so the 
 default rnf is sufficient. 
+-}
+instance NFData Int 
+instance NFData Integer
+instance NFData Float
+instance NFData Double
 
-> instance NFData Int 
-> instance NFData Integer
-> instance NFData Float
-> instance NFData Double
-
-> instance NFDataIntegral Int
-> instance NFDataOrd Int
-
-Rational and complex numbers.
-
->#if !(__HASKELL1__>=4)
-> instance (NFData a) => NFData (Ratio a) where
->   rnf (x:%y) = rnf x `seq` 
->                rnf y `seq`
->                ()
-
-> instance (NFData a) => NFData (Complex a) where
->   rnf (x:+y) = rnf x `seq` 
->               rnf y `seq`
->                ()
->#endif
+instance NFDataIntegral Int
+instance NFDataOrd Int
 
------------------------------------------------------------------------------
-                       Characters                                            
------------------------------------------------------------------------------
---@node Characters, Booleans, Numbers, Strategy Instances
---@subsection Characters
+--Rational and complex numbers.
 
-> instance NFData Char
+instance (Integral a, NFData a) => NFData (Ratio a) where
+  rnf (x:%y) = rnf x `seq` 
+               rnf y `seq`
+               ()
 
------------------------------------------------------------------------------
-                       Bools
------------------------------------------------------------------------------
---@node Booleans, Unit, Characters, Strategy Instances
---@subsection Booleans
+instance (RealFloat a, NFData a) => NFData (Complex a) where
+  rnf (x:+y) = rnf x `seq` 
+                rnf y `seq`
+               ()
 
-> instance NFData Bool
+instance NFData Char
+instance NFData Bool
+instance NFData ()
 
 -----------------------------------------------------------------------------
-                       Unit                                                 
------------------------------------------------------------------------------
---@node Unit, Lists, Booleans, Strategy Instances
---@subsection Unit
-
-> instance NFData ()
-
------------------------------------------------------------------------------
-                       Lists                                               
+--                     Lists                                               
 ----------------------------------------------------------------------------
---@node Lists, Arrays, Unit, Strategy Instances
---@subsection Lists
-
-> instance NFData a => NFData [a] where
->   rnf [] = ()
->   rnf (x:xs) = rnf x `seq` rnf xs
 
---@menu
---* Parallel Strategies for Lists::  
---* Sequential Strategies for Lists::  
---@end menu
+instance NFData a => NFData [a] where
+  rnf [] = ()
+  rnf (x:xs) = rnf x `seq` rnf xs
 
 ----------------------------------------------------------------------------
-                        Lists: Parallel Strategies
+--                        Lists: Parallel Strategies
 ----------------------------------------------------------------------------
---@node Parallel Strategies for Lists, Sequential Strategies for Lists, Lists, Lists
---@subsubsection Parallel Strategies for Lists
-
-Applies a strategy to every element of a list in parallel
-
---@cindex parList
-
-> parList :: Strategy a -> Strategy [a]
-> parList strat []     = ()
-> parList strat (x:xs) = strat x `par` (parList strat xs)
-
-Applies a strategy to the first  n elements of a list  in parallel
-
---@cindex parListN
-
-> parListN :: (Integral b) => b -> Strategy a -> Strategy [a]
-> parListN n strat []     = ()
-> parListN 0 strat xs     = ()
-> parListN n strat (x:xs) = strat x `par` (parListN (n-1) strat xs)
-
-Evaluates N elements of the spine of the argument list and applies
-`strat' to the Nth element (if there is one) in parallel with the
-result. e.g. parListNth 2 [e1, e2, e3] evaluates e2
-
---@cindex parListNth
-
-> parListNth :: Int -> Strategy a -> Strategy [a]
-> parListNth n strat xs 
->   | null rest = ()
->   | otherwise = strat (head rest) `par` ()
->   where
->     rest = drop n xs
-
-parListChunk sequentially applies a strategy to chunks
-(sub-sequences) of a list in parallel. Useful to increase grain size
-
---@cindex parListChunk
-
-> parListChunk :: Int -> Strategy a -> Strategy [a]
-> parListChunk n strat [] = ()
-> parListChunk n strat xs = seqListN n strat xs `par` 
->                          parListChunk n strat (drop n xs)
-
-parMap applies a function to each element of the argument list in
-parallel.  The result of the function is evaluated using `strat'
-
---@cindex parMap
-
-> parMap :: Strategy b -> (a -> b) -> [a] -> [b]
-> parMap strat f xs    = map f xs `using` parList strat
-
-parFlatMap uses parMap to apply a list-valued function to each
-element of the argument list in parallel.  The result of the function
-is evaluated using `strat'
 
---@cindex parFlatMap
-
-> parFlatMap :: Strategy [b] -> (a -> [b]) -> [a] -> [b]
-> parFlatMap strat f xs = concat (parMap strat f xs)
-
-parZipWith zips together two lists with a function z in parallel
-
---@cindex parZipWith
-
-> parZipWith :: Strategy c -> (a -> b -> c) -> [a] -> [b] -> [c]
-> parZipWith strat z as bs = 
->   zipWith z as bs `using` parList strat
+-- | Applies a strategy to every element of a list in parallel
+parList :: Strategy a -> Strategy [a]
+parList strat []     = ()
+parList strat (x:xs) = strat x `par` (parList strat xs)
+
+-- | Applies a strategy to the first  n elements of a list  in parallel
+parListN :: (Integral b) => b -> Strategy a -> Strategy [a]
+parListN n strat []     = ()
+parListN 0 strat xs     = ()
+parListN n strat (x:xs) = strat x `par` (parListN (n-1) strat xs)
+
+-- | Evaluates N elements of the spine of the argument list and applies
+-- `strat' to the Nth element (if there is one) in parallel with the
+-- result. e.g. parListNth 2 [e1, e2, e3] evaluates e2
+parListNth :: Int -> Strategy a -> Strategy [a]
+parListNth n strat xs 
+  | null rest = ()
+  | otherwise = strat (head rest) `par` ()
+  where
+    rest = drop n xs
+
+-- | 'parListChunk' sequentially applies a strategy to chunks
+-- (sub-sequences) of a list in parallel. Useful to increase grain size
+parListChunk :: Int -> Strategy a -> Strategy [a]
+parListChunk n strat [] = ()
+parListChunk n strat xs = seqListN n strat xs `par` 
+                           parListChunk n strat (drop n xs)
+
+-- | 'parMap' applies a function to each element of the argument list in
+-- parallel.  The result of the function is evaluated using `strat'
+parMap :: Strategy b -> (a -> b) -> [a] -> [b]
+parMap strat f xs      = map f xs `using` parList strat
+
+-- | 'parFlatMap' uses 'parMap' to apply a list-valued function to each
+-- element of the argument list in parallel.  The result of the function
+-- is evaluated using `strat'
+parFlatMap :: Strategy [b] -> (a -> [b]) -> [a] -> [b]
+parFlatMap strat f xs = concat (parMap strat f xs)
+
+-- | 'parZipWith' zips together two lists with a function z in parallel
+parZipWith :: Strategy c -> (a -> b -> c) -> [a] -> [b] -> [c]
+parZipWith strat z as bs = 
+  zipWith z as bs `using` parList strat
 
 ----------------------------------------------------------------------------
-                        Lists: Sequential Strategies
+--                        Lists: Sequential Strategies
 ----------------------------------------------------------------------------
---@node Sequential Strategies for Lists,  , Parallel Strategies for Lists, Lists
---@subsubsection Sequential Strategies for Lists
-
-Sequentially applies a strategy to each element of a list
-
---@cindex seqList
-
-> seqList :: Strategy a -> Strategy [a]
-> seqList strat []     = ()
-> seqList strat (x:xs) = strat x `seq` (seqList strat xs)
-
-Sequentially applies a strategy to the first  n elements of a list
-
---@cindex seqListN
-
-> seqListN :: (Integral a) => a -> Strategy b -> Strategy [b]
-> seqListN n strat []     = ()
-> seqListN 0 strat xs     = ()
-> seqListN n strat (x:xs) = strat x `seq` (seqListN (n-1) strat xs)
-
-seqListNth applies a strategy to the Nth element of it's argument
-(if there is one) before returning the result. e.g. seqListNth 2 [e1,
-e2, e3] evaluates e2
-
---@cindex seqListNth
 
->#if (__HASKELL1__>=4)
-> seqListNth :: Int -> Strategy b -> Strategy [b]
->#else
-> seqListNth :: (Integral a) => a -> Strategy b -> Strategy [b]
->#endif
-> seqListNth n strat xs 
->   | null rest = ()
->   | otherwise = strat (head rest) 
->   where
->     rest = drop n xs
+-- | Sequentially applies a strategy to each element of a list
+seqList :: Strategy a -> Strategy [a]
+seqList strat []     = ()
+seqList strat (x:xs) = strat x `seq` (seqList strat xs)
+
+-- | Sequentially applies a strategy to the first  n elements of a list
+seqListN :: (Integral a) => a -> Strategy b -> Strategy [b]
+seqListN n strat []     = ()
+seqListN 0 strat xs     = ()
+seqListN n strat (x:xs) = strat x `seq` (seqListN (n-1) strat xs)
+
+-- | 'seqListNth' applies a strategy to the Nth element of it's argument
+-- (if there is one) before returning the result. e.g. seqListNth 2 [e1,
+-- e2, e3] evaluates e2
+seqListNth :: Int -> Strategy b -> Strategy [b]
+seqListNth n strat xs 
+  | null rest = ()
+  | otherwise = strat (head rest) 
+  where
+    rest = drop n xs
+
+-- | Parallel n-buffer function added for the revised version of the strategies
+-- paper. 'parBuffer' supersedes the older 'fringeList'. It has the same
+-- semantics.
+parBuffer :: Int -> Strategy a -> [a] -> [a]
+parBuffer n s xs = 
+  return xs (start n xs)
+  where
+    return (x:xs) (y:ys) = (x:return xs ys) `sparking` s y
+    return xs     []     = xs
+
+    start n []     = []
+    start 0 ys     = ys
+    start n (y:ys) = start (n-1) ys `sparking` s y
 
-Parallel n-buffer function added for the revised version of the strategies
-paper. @parBuffer@ supersedes the older @fringeList@. It has the same
-semantics.
-
---@cindex parBuffer
-
-> parBuffer :: Int -> Strategy a -> [a] -> [a]
-> parBuffer n s xs = 
->   return xs (start n xs)
->   where
->     return (x:xs) (y:ys) = (x:return xs ys) `sparking` s y
->     return xs     []     = xs
->
->     start n []     = []
->     start 0 ys     = ys
->     start n (y:ys) = start (n-1) ys `sparking` s y
-
-fringeList implements a `rolling buffer' of length n, i.e.applies a
-strategy to the nth element of list when the head is demanded. More
-precisely:
+{-
+ 'fringeList' implements a `rolling buffer' of length n, i.e.applies a
+ strategy to the nth element of list when the head is demanded. More
+ precisely:
 
    semantics:         fringeList n s = id :: [b] -> [b]
    dynamic behaviour: evalutates the nth element of the list when the
                      head is demanded.
    
-The idea is to provide a `rolling buffer' of length n.
-
---@cindex fringeList
-
-<> fringeList :: (Integral a) => a -> Strategy b -> [b] -> [b]
-<> fringeList n strat [] = []
-<> fringeList n strat (r:rs) = 
-<>   seqListNth n strat rs `par`
-<>   r:fringeList n strat rs
+ The idea is to provide a `rolling buffer' of length n.
+fringeList :: (Integral a) => a -> Strategy b -> [b] -> [b]
+fringeList n strat [] = []
+fringeList n strat (r:rs) = 
+  seqListNth n strat rs `par`
+  r:fringeList n strat rs
+-}
 
 ------------------------------------------------------------------------------
-                       Arrays
+--                     Arrays
 ------------------------------------------------------------------------------
---@node Arrays,  , Lists, Strategy Instances
---@subsection Arrays
+instance (Ix a, NFData a, NFData b) => NFData (Array a b) where
+  rnf x = rnf (bounds x) `seq` seqList rnf (elems x) `seq` ()
 
-> instance (Ix a, NFData a, NFData b) => NFData (Array a b) where
->   rnf x = rnf (bounds x) `seq` seqList rnf (elems x) `seq` ()
+-- | Apply a strategy to all elements of an array in parallel. This can be done 
+-- either in sequentially or in parallel (same as with lists, really).
+seqArr :: (Ix b) => Strategy a -> Strategy (Array b a)
+seqArr s arr = seqList s (elems arr)
 
-Apply a strategy to all elements of an array in parallel. This can be done 
-either in sequentially or in parallel (same as with lists, really).
+parArr :: (Ix b) => Strategy a -> Strategy (Array b a)
+parArr s arr = parList s (elems arr)
 
-> seqArr :: (Ix b) => Strategy a -> Strategy (Array b a)
-> seqArr s arr = seqList s (elems arr)
+-- Associations maybe useful even without mentioning Arrays.
 
-> parArr :: (Ix b) => Strategy a -> Strategy (Array b a)
-> parArr s arr = parList s (elems arr)
-
-Associations maybe useful even withou mentioning Arrays.
-
-See: .../lib/prelude/TyArrays.hs:
 data  Assoc a b =  a := b  deriving ()
 
->#if (__HASKELL1__<4)
-> instance (NFData a, NFData b) => NFData (Assoc a b) where
->   rnf (x := y) = rnf x `seq` rnf y `seq` ()
->#endif
+instance (NFData a, NFData b) => NFData (Assoc a b) where
+  rnf (x := y) = rnf x `seq` rnf y `seq` ()
 
 ------------------------------------------------------------------------------
-                       Some strategies specific for Lolita     
+--                     Some strategies specific for Lolita     
 ------------------------------------------------------------------------------
---@node Lolita-specific Strategies, Index, Strategy Instances, Evaluation Strategies
---@section Lolita-specific Strategies
-
-The following is useful in mergePenGroups
-
---@cindex fstPairFstList
-
-> fstPairFstList :: (NFData a) => Strategy [(a,b)]
-> fstPairFstList = seqListN 1 (seqPair rwhnf r0)
-
-Some HACKs for Lolita. AFAIK force is just another name for our rnf and
-sforce is a shortcut (definition here is identical to the one in Force.lhs)
-
-> force :: (NFData a) => a -> a 
-> sforce :: (NFData a) => a -> b -> b
-
-Same as definition below
-
-<> force x = rnf x `seq` x
-
-> force = id $| rnf
->#if (__HASKELL1__>=4)
-> sforce x y = force x `seq` y
->#else
-> sforce x y = force x `seq_from_Parallel` y
->#endif
-
---@node Bowing-alg specific strategies
---@section Bowing-alg specific strategies
-
-NB: this strategy currently needs the quicksort implementation from the hbc syslib 
-
->#if defined(PAR_GRAN_LIST)
-> parGranList :: Strategy a -> (a -> Int) -> [a] -> Strategy [a]
-> parGranList s gran_estim l_in = \ l_out ->
->   parListByIdx s l_out $
->   sortedIdx gran_list (sortLe ( \ (i,_) (j,_) -> i>j) gran_list)
->   where -- spark list elems of l in the order specified by  (i:idxs)
->        parListByIdx s l [] = ()
->        parListByIdx s l (i:idxs) = parListByIdx s l idxs `sparking` s (l!!i)
->        -- get the index of y in the list
->        idx y [] = error "idx: x not in l"
->        idx y ((x,_):xs) | y==x      = 0
->                        | otherwise = (idx y xs)+1
->        -- the `schedule' for sparking: list of indices of sorted input list
->        sortedIdx l idxs = [ idx x l | (x,_) <- idxs ]
->        -- add granularity info to elems of the input list
->        gran_list = map (\ l -> (gran_estim l, l)) l_in  
->#endif
-
---@node Index,  , Lolita-specific Strategies, Evaluation Strategies
---@section Index
-
---@index
---* $|::  @cindex\s-+$|
---* $||::  @cindex\s-+$||
---* -|::  @cindex\s-+-|
---* -||::  @cindex\s-+-||
---* .|::  @cindex\s-+.|
---* .||::  @cindex\s-+.||
---* NFData::  @cindex\s-+NFData
---* Strategy::  @cindex\s-+Strategy
---* demanding::  @cindex\s-+demanding
---* fringeList::  @cindex\s-+fringeList
---* fstPairFstList::  @cindex\s-+fstPairFstList
---* markStrat::  @cindex\s-+markStrat
---* parBuffer::  @cindex\s-+parBuffer
---* parFlatMap::  @cindex\s-+parFlatMap
---* parList::  @cindex\s-+parList
---* parListChunk::  @cindex\s-+parListChunk
---* parListN::  @cindex\s-+parListN
---* parListNth::  @cindex\s-+parListNth
---* parMap::  @cindex\s-+parMap
---* parPair::  @cindex\s-+parPair
---* parTriple::  @cindex\s-+parTriple
---* parZipWith::  @cindex\s-+parZipWith
---* r0::  @cindex\s-+r0
---* rnf::  @cindex\s-+rnf
---* rwhnf::  @cindex\s-+rwhnf
---* seqList::  @cindex\s-+seqList
---* seqListN::  @cindex\s-+seqListN
---* seqListNth::  @cindex\s-+seqListNth
---* seqPair::  @cindex\s-+seqPair
---* seqTriple::  @cindex\s-+seqTriple
---* sparking::  @cindex\s-+sparking
---* using::  @cindex\s-+using
---@end index
+
+fstPairFstList :: (NFData a) => Strategy [(a,b)]
+fstPairFstList = seqListN 1 (seqPair rwhnf r0)
+
+-- Some HACKs for Lolita. AFAIK force is just another name for our rnf and
+-- sforce is a shortcut (definition here is identical to the one in Force.lhs)
+
+force :: (NFData a) => a -> a 
+sforce :: (NFData a) => a -> b -> b
+
+force = id $| rnf
+sforce x y = force x `seq` y