[project @ 2001-10-25 02:13:10 by sof]
authorsof <unknown>
Thu, 25 Oct 2001 02:13:16 +0000 (02:13 +0000)
committersof <unknown>
Thu, 25 Oct 2001 02:13:16 +0000 (02:13 +0000)
- Pet peeve removal / code tidyup, replaced various sub-optimal
  uses of 'length' with something a bit better, i.e., replaced
  the following patterns

   *  length as `cmpOp` length bs
   *  length as `cmpOp` val   -- incl. uses where val == 1 and val == 0
   *  {take,drop,splitAt} (length as) bs
   *  length [ () | pat <- as ]

  with uses of misc Util functions.

  I'd be surprised if there's a noticeable reduction in running
  times as a result of these changes, but every little bit helps.

  [ The changes have been tested wrt testsuite/ - I'm seeing a couple
    of unexpected breakages coming from CorePrep, but I'm currently
    assuming that these are due to other recent changes. ]

- compMan/CompManager.lhs: restored 4.08 compilability + some code
  cleanup.

None of these changes are HEADworthy.

63 files changed:
ghc/compiler/absCSyn/PprAbsC.lhs
ghc/compiler/basicTypes/BasicTypes.lhs
ghc/compiler/basicTypes/DataCon.lhs
ghc/compiler/basicTypes/Demand.lhs
ghc/compiler/basicTypes/IdInfo.lhs
ghc/compiler/basicTypes/MkId.lhs
ghc/compiler/basicTypes/NewDemand.lhs
ghc/compiler/codeGen/CgClosure.lhs
ghc/compiler/codeGen/CgCon.lhs
ghc/compiler/codeGen/CgExpr.lhs
ghc/compiler/codeGen/CgLetNoEscape.lhs
ghc/compiler/codeGen/ClosureInfo.lhs
ghc/compiler/compMan/CompManager.lhs
ghc/compiler/coreSyn/CorePrep.lhs
ghc/compiler/coreSyn/CoreUtils.lhs
ghc/compiler/coreSyn/PprCore.lhs
ghc/compiler/deSugar/Check.lhs
ghc/compiler/deSugar/DsUtils.lhs
ghc/compiler/deSugar/Match.lhs
ghc/compiler/ghci/ByteCodeGen.lhs
ghc/compiler/hsSyn/HsCore.lhs
ghc/compiler/hsSyn/HsDecls.lhs
ghc/compiler/hsSyn/HsTypes.lhs
ghc/compiler/ilxGen/IlxGen.lhs
ghc/compiler/javaGen/JavaGen.lhs
ghc/compiler/main/ErrUtils.lhs
ghc/compiler/main/HscMain.lhs
ghc/compiler/main/HscStats.lhs
ghc/compiler/main/Main.hs
ghc/compiler/prelude/TysPrim.lhs
ghc/compiler/simplCore/CSE.lhs
ghc/compiler/simplCore/FloatIn.lhs
ghc/compiler/simplCore/SATMonad.lhs
ghc/compiler/simplStg/SRT.lhs
ghc/compiler/specialise/Rules.lhs
ghc/compiler/specialise/SpecConstr.lhs
ghc/compiler/specialise/Specialise.lhs
ghc/compiler/stgSyn/CoreToStg.lhs
ghc/compiler/stgSyn/StgLint.lhs
ghc/compiler/stranal/DmdAnal.lhs
ghc/compiler/stranal/SaAbsInt.lhs
ghc/compiler/stranal/StrictAnal.lhs
ghc/compiler/stranal/WorkWrap.lhs
ghc/compiler/typecheck/Inst.lhs
ghc/compiler/typecheck/TcBinds.lhs
ghc/compiler/typecheck/TcClassDcl.lhs
ghc/compiler/typecheck/TcExpr.lhs
ghc/compiler/typecheck/TcGenDeriv.lhs
ghc/compiler/typecheck/TcIfaceSig.lhs
ghc/compiler/typecheck/TcInstDcls.lhs
ghc/compiler/typecheck/TcMType.lhs
ghc/compiler/typecheck/TcMatches.lhs
ghc/compiler/typecheck/TcMonad.lhs
ghc/compiler/typecheck/TcMonoType.lhs
ghc/compiler/typecheck/TcType.lhs
ghc/compiler/types/Generics.lhs
ghc/compiler/types/PprType.lhs
ghc/compiler/types/TyCon.lhs
ghc/compiler/types/Type.lhs
ghc/compiler/usageSP/UsageSPInf.lhs
ghc/compiler/usageSP/UsageSPUtils.lhs
ghc/compiler/utils/Digraph.lhs
ghc/compiler/utils/Util.lhs

index 2793d0f..4a0abfc 100644 (file)
@@ -57,7 +57,7 @@ import StgSyn         ( StgOp(..) )
 import BitSet          ( BitSet, intBS )
 import Outputable
 import GlaExts
-import Util            ( nOfThem )
+import Util            ( nOfThem, lengthExceeds, listLengthCmp )
 
 import ST
 
@@ -349,7 +349,7 @@ pprAbsC stmt@(CCallTypedef is_tdef (CCallSpec op_str cconv _) uniq results args)
       -- should ignore and a (possibly void) result.
      non_void_results =
        let nvrs = grab_non_void_amodes results
-       in ASSERT (length nvrs <= 1) nvrs
+       in ASSERT (listLengthCmp nvrs 1 /= GT) nvrs
 
 pprAbsC (CCodeBlock lbl abs_C) _
   = if not (maybeToBool(nonemptyAbsC abs_C)) then
@@ -800,7 +800,7 @@ pprFCall call@(CCall (CCallSpec target cconv safety)) uniq args results vol_regs
 
     non_void_results =
        let nvrs = grab_non_void_amodes results
-       in ASSERT (length nvrs <= 1) nvrs
+       in ASSERT (listLengthCmp nvrs 1 /= GT) nvrs
     -- there will usually be two results: a (void) state which we
     -- should ignore and a (possibly void) result.
 
@@ -947,7 +947,7 @@ process_casm results args string = process results args string
          in
          case (read_int other) of
            [(num,css)] ->
-                 if 0 <= num && num < length args
+                 if num >= 0 && args `lengthExceeds` num
                  then parens (args !! num) <> process ress args css
                  else error ("process_casm: no such arg #:"++(show num)++" while processing \"" ++ string ++ "\".\n")
            _ -> error ("process_casm: not %<num> while processing _casm_ \"" ++ string ++ "\".\n")
index a4e6260..ba6663b 100644 (file)
@@ -377,4 +377,4 @@ isNeverActive act     = False
 
 isAlwaysActive AlwaysActive = True
 isAlwaysActive other       = False
-\end{code}
\ No newline at end of file
+\end{code}
index 077e138..917f474 100644 (file)
@@ -42,7 +42,7 @@ import Unique         ( Unique, Uniquable(..) )
 import CmdLineOpts     ( opt_UnboxStrictFields )
 import Maybe
 import ListSetOps      ( assoc )
-import Util            ( zipEqual, zipWithEqual )
+import Util            ( zipEqual, zipWithEqual, equalLength )
 \end{code}
 
 
@@ -216,7 +216,7 @@ mkDataCon :: Name
 mkDataCon name arg_stricts fields
          tyvars theta ex_tyvars ex_theta orig_arg_tys tycon
          work_id wrap_id
-  = ASSERT(length arg_stricts == length orig_arg_tys)
+  = ASSERT(equalLength arg_stricts orig_arg_tys)
        -- The 'stricts' passed to mkDataCon are simply those for the
        -- source-language arguments.  We add extra ones for the
        -- dictionary arguments right here.
index b39ad98..8e8f24f 100644 (file)
@@ -23,6 +23,7 @@ module Demand(
 #include "HsVersions.h"
 
 import Outputable
+import Util ( listLengthCmp )
 \end{code}
 
 
@@ -191,7 +192,7 @@ isBottomingStrictness (StrictnessInfo _ bot) = bot
 isBottomingStrictness NoStrictnessInfo       = False
 
 -- appIsBottom returns true if an application to n args would diverge
-appIsBottom (StrictnessInfo ds bot)   n = bot && (n >= length ds)
+appIsBottom (StrictnessInfo ds bot)   n = bot && (listLengthCmp ds n /=GT) -- not more than 'n' elts in 'ds'.
 appIsBottom  NoStrictnessInfo        n = False
 
 ppStrictnessInfo NoStrictnessInfo                 = empty
index 1aecb54..017b3eb 100644 (file)
@@ -101,7 +101,7 @@ import NewDemand    ( Demand(..), Keepity(..), DmdResult(..),
                          StrictSig, mkStrictSig, mkTopDmdType
                        )
 import Outputable      
-import Util            ( seqList )
+import Util            ( seqList, listLengthCmp )
 import List            ( replicate )
 
 infixl         1 `setDemandInfo`,
@@ -133,7 +133,7 @@ To be removed later
 \begin{code}
 mkNewStrictnessInfo :: Id -> Arity -> Demand.StrictnessInfo -> CprInfo -> StrictSig
 mkNewStrictnessInfo id arity (Demand.StrictnessInfo ds res) cpr
-  | length ds <= arity
+  | listLengthCmp ds arity /= GT -- length ds <= arity
        -- Sometimes the old strictness analyser has more
        -- demands than the arity justifies
   = mk_strict_sig id arity $
index 6c53312..5262fa5 100644 (file)
@@ -87,6 +87,7 @@ import Unique         ( mkBuiltinUnique )
 import Maybes
 import PrelNames
 import Maybe            ( isJust )
+import Util             ( dropList, isSingleton )
 import Outputable
 import ListSetOps      ( assoc, assocMaybe )
 import UnicodeUtil      ( stringToUtf8 )
@@ -256,7 +257,7 @@ mkDataConWrapId data_con
        -- we want to see that w is strict in its two arguments
 
     wrap_rhs | isNewTyCon tycon
-            = ASSERT( null ex_tyvars && null ex_dict_args && length orig_arg_tys == 1 )
+            = ASSERT( null ex_tyvars && null ex_dict_args && isSingleton orig_arg_tys )
                -- No existentials on a newtype, but it can have a context
                -- e.g.         newtype Eq a => T a = MkT (...)
                mkLams tyvars $ mkLams dict_args $ Lam id_arg1 $ 
@@ -537,7 +538,7 @@ rebuildConArgs (arg:args) (str:stricts) us
                 = splitProductType "rebuildConArgs" arg_ty
 
        unpacked_args  = zipWith (mkSysLocal SLIT("rb")) us con_arg_tys
-       (binds, args') = rebuildConArgs args stricts (drop (length con_arg_tys) us)
+       (binds, args') = rebuildConArgs args stricts (dropList con_arg_tys us)
        con_app        = mkConApp pack_con (map Type tycon_args ++ map Var unpacked_args)
     in
     (NonRec arg con_app : binds, unpacked_args ++ args')
index 554c080..532ad46 100644 (file)
@@ -23,6 +23,7 @@ module NewDemand(
 import BasicTypes      ( Arity )
 import VarEnv          ( VarEnv, emptyVarEnv, isEmptyVarEnv )
 import UniqFM          ( ufmToList )
+import Util             ( listLengthCmp )
 import Outputable
 \end{code}
 
@@ -169,7 +170,7 @@ topSig = StrictSig topDmdType
 botSig = StrictSig botDmdType
 
 -- appIsBottom returns true if an application to n args would diverge
-appIsBottom (StrictSig (DmdType _ ds BotRes)) n = n >= length ds
+appIsBottom (StrictSig (DmdType _ ds BotRes)) n = listLengthCmp ds n /= GT
 appIsBottom _                                _ = False
 
 isBottomingSig (StrictSig (DmdType _ _ BotRes)) = True
index 28bc6c1..48905e9 100644 (file)
@@ -1,7 +1,7 @@
 %
 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
 %
-% $Id: CgClosure.lhs,v 1.50 2001/10/03 13:59:22 simonpj Exp $
+% $Id: CgClosure.lhs,v 1.51 2001/10/25 02:13:11 sof Exp $
 %
 \section[CgClosure]{Code generation for closures}
 
@@ -51,7 +51,7 @@ import Module         ( Module, pprModule )
 import ListSetOps      ( minusList )
 import PrimRep         ( PrimRep(..) )
 import PprType          ( showTypeCategory )
-import Util            ( isIn )
+import Util            ( isIn, splitAtList )
 import CmdLineOpts     ( opt_SccProfilingOn )
 import Outputable
 
@@ -328,9 +328,7 @@ closureCodeBody binder_info closure_info cc all_args body
                DirectEntry lbl arity regs -> regs
                other                      -> []  -- "(HWL ignored; no args passed in regs)"
 
-       num_arg_regs = length arg_regs
-       
-       (reg_args, stk_args) = splitAt num_arg_regs all_args
+       (reg_args, stk_args) = splitAtList arg_regs all_args
 
        (sp_stk_args, stk_offsets, stk_tags)
          = mkTaggedVirtStkOffsets vSp idPrimRep stk_args
index 954dca8..1e0fa93 100644 (file)
@@ -69,8 +69,8 @@ cgTopRhsCon :: Id             -- Name of thing bound to this RHS
            -> [StgArg]         -- Args
            -> FCode (Id, CgIdInfo)
 cgTopRhsCon id con args
-  = ASSERT(not (isDllConApp con args)) -- checks for litlit args too
-    ASSERT(length args == dataConRepArity con)
+  = ASSERT( not (isDllConApp con args) )       -- checks for litlit args too
+    ASSERT( args `lengthIs` dataConRepArity con )
 
        -- LAY IT OUT
     getArgAmodes args          `thenFC` \ amodes ->
@@ -234,7 +234,7 @@ bindUnboxedTupleComponents
 bindUnboxedTupleComponents args
  =  -- Assign as many components as possible to registers
     let (arg_regs, _leftovers) = assignRegs [] (map idPrimRep args)
-       (reg_args, stk_args)   = splitAt (length arg_regs) args
+       (reg_args, stk_args)   = splitAtList arg_regs args
     in
 
     -- Allocate the rest on the stack (ToDo: separate out pointers)
@@ -268,7 +268,7 @@ sure the @amodes@ passed don't conflict with each other.
 cgReturnDataCon :: DataCon -> [CAddrMode] -> Code
 
 cgReturnDataCon con amodes
-  = ASSERT(length amodes == dataConRepArity con)
+  = ASSERT( amodes `lengthIs` dataConRepArity con )
     getEndOfBlockInfo  `thenFC` \ (EndOfBlockInfo args_sp sequel) ->
 
     case sequel of
index 6297949..a98a1bb 100644 (file)
@@ -1,7 +1,7 @@
 %
 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
 %
-% $Id: CgExpr.lhs,v 1.45 2001/10/17 14:24:52 simonmar Exp $
+% $Id: CgExpr.lhs,v 1.46 2001/10/25 02:13:11 sof Exp $
 %
 %********************************************************
 %*                                                     *
@@ -48,6 +48,7 @@ import Maybes         ( maybeToBool )
 import ListSetOps      ( assocMaybe )
 import Unique          ( mkBuiltinUnique )
 import BasicTypes      ( TopLevelFlag(..), RecFlag(..) )
+import Util             ( lengthIs )
 import Outputable
 \end{code}
 
@@ -362,7 +363,7 @@ mkRhsClosure        bndr cc bi srt
                []                      -- No args; a thunk
                body@(StgApp fun_id args)
 
-  | length args + 1 == arity
+  | args `lengthIs` (arity-1)
        && all isFollowableRep (map idPrimRep fvs) 
        && isUpdatable upd_flag
        && arity <= mAX_SPEC_AP_SIZE 
index a5b0a20..8562b67 100644 (file)
@@ -1,7 +1,7 @@
 %
 % (c) The GRASP/AQUA Project, Glasgow University, 1993-1998
 %
-% $Id: CgLetNoEscape.lhs,v 1.15 2001/09/26 15:11:50 simonpj Exp $
+% $Id: CgLetNoEscape.lhs,v 1.16 2001/10/25 02:13:11 sof Exp $
 %
 %********************************************************
 %*                                                     *
@@ -35,8 +35,9 @@ import CostCentre       ( CostCentreStack )
 import Id              ( idPrimRep, Id )
 import Var             ( idUnique )
 import PrimRep         ( PrimRep(..), retPrimRepSize )
-import Unique          ( Unique )
 import BasicTypes      ( RecFlag(..) )
+import Unique          ( Unique )
+import Util            ( splitAtList )
 \end{code}
 
 %************************************************************************
@@ -198,7 +199,7 @@ cgLetNoEscapeBody binder cc all_args body uniq
      let
        arg_kinds            = map idPrimRep all_args
        (arg_regs, _)        = assignRegs [{-nothing live-}] arg_kinds
-       (reg_args, stk_args) = splitAt (length arg_regs) all_args
+       (reg_args, stk_args) = splitAtList arg_regs all_args
 
        (sp_stk_args, stk_offsets, stk_tags)
          = mkTaggedVirtStkOffsets sp idPrimRep stk_args
index b7e6ace..dcd2176 100644 (file)
@@ -1,7 +1,7 @@
 %
 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
 %
-% $Id: ClosureInfo.lhs,v 1.49 2001/10/18 16:29:13 simonpj Exp $
+% $Id: ClosureInfo.lhs,v 1.50 2001/10/25 02:13:11 sof Exp $
 %
 \section[ClosureInfo]{Data structures which describe closures}
 
@@ -89,7 +89,7 @@ import PrimRep                ( getPrimRepSize, separateByPtrFollowness, PrimRep )
 import SMRep           -- all of it
 import Type            ( isUnLiftedType, Type )
 import BasicTypes      ( TopLevelFlag(..), isNotTopLevel, isTopLevel )
-import Util            ( mapAccumL )
+import Util            ( mapAccumL, listLengthCmp, lengthIs )
 import Outputable
 \end{code}
 
@@ -635,7 +635,7 @@ getEntryConvention name lf_info arg_kinds
     case lf_info of
 
        LFReEntrant _ _ arity _ ->
-           if arity == 0 || (length arg_kinds) < arity then
+           if arity == 0 || (listLengthCmp arg_kinds arity == LT) then
                StdEntry (mkStdEntryLabel name)
            else
                DirectEntry (mkFastEntryLabel name arity) arity arg_regs
@@ -678,7 +678,7 @@ getEntryConvention name lf_info arg_kinds
          -> StdEntry (mkReturnPtLabel (nameUnique name))
 
        LFLetNoEscape arity
-         -> if (arity /= length arg_kinds) then pprPanic "let-no-escape: " (ppr name <+> ppr arity) else
+         -> if (not (arg_kinds `lengthIs` arity)) then pprPanic "let-no-escape: " (ppr name <+> ppr arity) else
             DirectEntry (mkReturnPtLabel (nameUnique name)) arity arg_regs
         where
            (arg_regs, _) = assignRegs [] arg_kinds
index 1642b26..dbd26ce 100644 (file)
@@ -77,11 +77,12 @@ import IOExts
 import Interpreter     ( HValue )
 import HscMain         ( hscStmt )
 import PrelGHC         ( unsafeCoerce# )
-#endif
 
 -- lang
 import Foreign
 import CForeign
+#endif
+
 import Exception       ( Exception, try, throwDyn )
 
 -- std
@@ -828,9 +829,7 @@ findInSummaries old_summaries mod_name
 
 findModInSummaries :: [ModSummary] -> Module -> Maybe ModSummary
 findModInSummaries old_summaries mod
-   = case [s | s <- old_summaries, ms_mod s == mod] of
-        [] -> Nothing
-        (s:_) -> Just s
+   = listToMaybe [s | s <- old_summaries, ms_mod s == mod]
 
 -- Return (names of) all those in modsDone who are part of a cycle
 -- as defined by theGraph.
@@ -848,7 +847,7 @@ findPartiallyCompletedCycles modsDone theGraph
                  chewed_rest = chew rest
              in 
              if   not (null mods_in_this_cycle) 
-                  && length mods_in_this_cycle < length names_in_this_cycle
+                  && compareLength mods_in_this_cycle names_in_this_cycle == LT
              then mods_in_this_cycle ++ chewed_rest
              else chewed_rest
 
@@ -1018,7 +1017,7 @@ simple_transitive_closure graph set
    = let set2      = nub (concatMap dsts set ++ set)
          dsts node = fromMaybe [] (lookup node graph)
      in
-         if   length set == length set2
+         if   equalLength set set2
          then set
          else simple_transitive_closure graph set2
 
@@ -1071,22 +1070,29 @@ downsweep rootNm old_summaries
        getRootSummary file
           | haskellish_src_file file
           = do exists <- doesFileExist file
-               if exists then summariseFile file else do
-               throwDyn (CmdLineError ("can't find file `" ++ file ++ "'"))    
+               when (not exists)
+                    (throwDyn (CmdLineError ("can't find file `" ++ file ++ "'")))
+               summariseFile file
           | otherwise
-          = do exists <- doesFileExist hs_file
-               if exists then summariseFile hs_file else do
-               exists <- doesFileExist lhs_file
-               if exists then summariseFile lhs_file else do
-               let mod_name = mkModuleName file
-               maybe_summary <- getSummary mod_name
-               case maybe_summary of
-                  Nothing -> packageModErr mod_name
-                  Just s  -> return s
+          = do mb_file <- findFile [hs_file, lhs_file]
+               case mb_file of
+                 Just x  -> summariseFile x
+                 Nothing -> do
+                    let mod_name = mkModuleName file
+                    maybe_summary <- getSummary mod_name
+                    case maybe_summary of
+                      Nothing -> packageModErr mod_name
+                      Just s  -> return s
            where 
                 hs_file = file ++ ".hs"
                 lhs_file = file ++ ".lhs"
 
+        findFile :: [FilePath] -> IO (Maybe FilePath)
+       findFile [] = return Nothing
+       findFile (x:xs) = do
+           flg <- doesFileExist x
+           if flg then return (Just x) else findFile xs
+
         getSummary :: ModuleName -> IO (Maybe ModSummary)
         getSummary nm
            = do found <- findModule nm
index eb543a3..906cd6d 100644 (file)
@@ -37,6 +37,7 @@ import Maybes
 import OrdList
 import ErrUtils
 import CmdLineOpts
+import Util       ( listLengthCmp )
 import Outputable
 \end{code}
 
@@ -415,8 +416,9 @@ corePrepExprFloat env expr@(App _ _)
        where
          stricts = case idNewStrictness v of
                        StrictSig (DmdType _ demands _)
-                           | depth >= length demands -> demands
-                           | otherwise               -> []
+                           | listLengthCmp demands depth /= GT -> demands
+                                   -- length demands <= depth
+                           | otherwise                         -> []
                -- If depth < length demands, then we have too few args to 
                -- satisfy strictness  info so we have to  ignore all the 
                -- strictness info, e.g. + (error "urk")
index 2cd4249..a1a4694 100644 (file)
@@ -68,6 +68,7 @@ import BasicTypes     ( Arity )
 import Unique          ( Unique )
 import Outputable
 import TysPrim         ( alphaTy )     -- Debugging only
+import Util             ( equalLength, lengthAtLeast )
 \end{code}
 
 
@@ -623,7 +624,7 @@ exprIsConApp_maybe (Note (Coerce to_ty from_ty) expr)
        new_val_args     = zipWith mk_coerce to_arg_tys val_args
     in
     ASSERT( all isTypeArg (take arity args) )
-    ASSERT( length val_args == length to_arg_tys )
+    ASSERT( equalLength val_args to_arg_tys )
     Just (dc, map Type tc_arg_tys ++ new_val_args)
     }}
 
@@ -644,7 +645,7 @@ exprIsConApp_maybe expr = analyse (collectArgs expr)
   where
     analyse (Var fun, args)
        | Just con <- isDataConId_maybe fun,
-         length args >= dataConRepArity con
+         args `lengthAtLeast` dataConRepArity con
                -- Might be > because the arity excludes type args
        = Just (con,args)
 
@@ -961,7 +962,7 @@ eqExpr e1 e2
     eq env (Let (NonRec v1 r1) e1)
           (Let (NonRec v2 r2) e2)   = eq env r1 r2 && eq (extendVarEnv env v1 v2) e1 e2
     eq env (Let (Rec ps1) e1)
-          (Let (Rec ps2) e2)        = length ps1 == length ps2 &&
+          (Let (Rec ps2) e2)        = equalLength ps1 ps2 &&
                                       and (zipWith eq_rhs ps1 ps2) &&
                                       eq env' e1 e2
                                     where
@@ -969,7 +970,7 @@ eqExpr e1 e2
                                       eq_rhs (_,r1) (_,r2) = eq env' r1 r2
     eq env (Case e1 v1 a1)
           (Case e2 v2 a2)           = eq env e1 e2 &&
-                                      length a1 == length a2 &&
+                                      equalLength a1 a2 &&
                                       and (zipWith (eq_alt env') a1 a2)
                                     where
                                       env' = extendVarEnv env v1 v2
index f19c28c..85fd027 100644 (file)
@@ -38,6 +38,7 @@ import TyCon          ( tupleTyConBoxity, isTupleTyCon )
 import PprType         ( pprParendType, pprTyVarBndr )
 import BasicTypes      ( tupleParens )
 import PprEnv
+import Util             ( lengthIs )
 import Outputable
 \end{code}
 
@@ -184,7 +185,7 @@ ppr_expr add_par pe expr@(App fun arg)
                           -> tupleParens (tupleTyConBoxity tc) pp_tup_args
                           where
                             tc        = dataConTyCon dc
-                            saturated = length val_args == idArity f
+                            saturated = val_args `lengthIs` idArity f
 
                   other -> add_par (hang (pOcc pe f) 2 pp_args)
 
index 0d8e76a..b679729 100644 (file)
@@ -28,6 +28,7 @@ import TyCon            ( tyConDataCons, tupleTyConBoxity, isTupleTyCon )
 import BasicTypes      ( Boxity(..) )
 import SrcLoc          ( noSrcLoc )
 import UniqSet
+import Util             ( takeList, splitAtList )
 import Outputable
 
 #include "HsVersions.h"
@@ -187,7 +188,7 @@ check' :: [EquationInfo] -> ([ExhaustivePat],EqnSet)
 check' []                                              = ([([],[])],emptyUniqSet)
 
 check' [EqnInfo n ctx ps (MatchResult CanFail _)] 
-   | all_vars ps  = ([(take (length ps) (repeat new_wild_pat),[])],  unitUniqSet n)
+   | all_vars ps  = ([(takeList ps (repeat new_wild_pat),[])],  unitUniqSet n)
 
 check' qs@((EqnInfo n ctx ps (MatchResult CanFail _)):rs)
    | all_vars ps  = (pats,  addOneToUniqSet indexs n)
@@ -244,8 +245,8 @@ must be one Variable to be complete.
 
 process_literals :: [HsLit] -> [EquationInfo] -> ([ExhaustivePat],EqnSet)
 process_literals used_lits qs 
-  | length default_eqns == 0 = ([make_row_vars used_lits (head qs)]++pats,indexs)
-  | otherwise                = (pats_default,indexs_default)
+  | null default_eqns  = ([make_row_vars used_lits (head qs)]++pats,indexs)
+  | otherwise          = (pats_default,indexs_default)
      where
        (pats,indexs)   = process_explicit_literals used_lits qs
        default_eqns    = (map remove_var (filter is_var qs))
@@ -283,8 +284,9 @@ same constructor.
 
 split_by_constructor :: [EquationInfo] -> ([ExhaustivePat],EqnSet)
 
-split_by_constructor qs | length unused_cons /= 0 = need_default_case used_cons unused_cons qs 
-                        | otherwise               = no_need_default_case used_cons qs 
+split_by_constructor qs 
+  | not (null unused_cons) = need_default_case used_cons unused_cons qs 
+  | otherwise              = no_need_default_case used_cons qs 
                        where 
                           used_cons   = get_used_cons qs 
                           unused_cons = get_unused_cons used_cons 
@@ -319,8 +321,8 @@ no_need_default_case cons qs = (concat pats, unionManyUniqSets indexs)
 
 need_default_case :: [TypecheckedPat] -> [DataCon] -> [EquationInfo] -> ([ExhaustivePat],EqnSet)
 need_default_case used_cons unused_cons qs 
-  | length default_eqns == 0 = (pats_default_no_eqns,indexs)
-  | otherwise                = (pats_default,indexs_default)
+  | null default_eqns  = (pats_default_no_eqns,indexs)
+  | otherwise          = (pats_default,indexs_default)
      where
        (pats,indexs)   = no_need_default_case used_cons qs
        default_eqns    = (map remove_var (filter is_var qs))
@@ -368,7 +370,7 @@ remove_first_column (ConPat con _ _ _ con_pats) qs =
 
 make_row_vars :: [HsLit] -> EquationInfo -> ExhaustivePat
 make_row_vars used_lits (EqnInfo _ _ pats _ ) = 
-   (VarPatIn new_var:take (length (tail pats)) (repeat new_wild_pat),[(new_var,used_lits)])
+   (VarPatIn new_var:takeList (tail pats) (repeat new_wild_pat),[(new_var,used_lits)])
   where new_var = hash_x
 
 hash_x = mkLocalName unboundKey {- doesn't matter much -}
@@ -376,7 +378,7 @@ hash_x = mkLocalName unboundKey {- doesn't matter much -}
                     noSrcLoc
 
 make_row_vars_for_constructor :: EquationInfo -> [WarningPat]
-make_row_vars_for_constructor (EqnInfo _ _ pats _ ) = take (length (tail pats)) (repeat new_wild_pat)
+make_row_vars_for_constructor (EqnInfo _ _ pats _ ) = takeList (tail pats) (repeat new_wild_pat)
 
 compare_cons :: TypecheckedPat -> TypecheckedPat -> Bool
 compare_cons (ConPat id1 _ _ _ _) (ConPat id2 _ _ _ _) = id1 == id2  
@@ -524,10 +526,8 @@ make_con (ConPat id _ _ _ _) (p:q:ps, constraints)
 make_con (ConPat id _ _ _ pats) (ps,constraints) 
       | isTupleTyCon tc = (TuplePatIn pats_con (tupleTyConBoxity tc) : rest_pats, constraints) 
       | otherwise       = (ConPatIn name pats_con                   : rest_pats, constraints)
-    where num_args  = length pats
-          name      = getName id
-          pats_con  = take num_args ps
-          rest_pats = drop num_args ps
+    where name      = getName id
+         (pats_con, rest_pats) = splitAtList pats ps
          tc        = dataConTyCon id
          
 
@@ -538,7 +538,7 @@ make_whole_con con | isInfixCon con = ConOpPatIn new_wild_pat name fixity new_wi
                   fixity = panic "Check.make_whole_con: Guessing fixity"
                   name   = getName con
                   arity  = dataConSourceArity con 
-                  pats   = take arity (repeat new_wild_pat)
+                  pats   = replicate arity new_wild_pat
 
 
 new_wild_pat :: WarningPat
index 008cebf..b83b784 100644 (file)
@@ -63,6 +63,7 @@ import PrelNames      ( unpackCStringName, unpackCStringUtf8Name,
                          plusIntegerName, timesIntegerName )
 import Outputable
 import UnicodeUtil      ( stringToUtf8 )
+import Util             ( isSingleton )
 \end{code}
 
 
@@ -430,7 +431,7 @@ mkSelectorBinds (VarPat v) val_expr
   = returnDs [(v, val_expr)]
 
 mkSelectorBinds pat val_expr
-  | length binders == 1 || is_simple_pat pat
+  | isSingleton binders || is_simple_pat pat
   = newSysLocalDs (exprType val_expr)  `thenDs` \ val_var ->
 
        -- For the error message we don't use mkErrorAppDs to avoid
index e56a8ab..5113913 100644 (file)
@@ -27,6 +27,7 @@ import TysWiredIn     ( nilDataCon, consDataCon, mkTupleTy, mkListTy, tupleCon )
 import BasicTypes      ( Boxity(..) )
 import UniqSet
 import ErrUtils                ( addWarnLocHdrLine, dontAddErrLoc )
+import Util             ( lengthExceeds )
 import Outputable
 \end{code}
 
@@ -62,7 +63,7 @@ matchExport_really dflags vars qs@((EqnInfo _ ctx _ (MatchResult _ _)) : _)
       match vars qs
   where (pats,indexs) = check qs
         incomplete    = dopt Opt_WarnIncompletePatterns dflags
-                       && (length pats /= 0)
+                       && (not (null pats))
         shadow        = dopt Opt_WarnOverlappingPatterns dflags
                        && sizeUniqSet indexs < no_eqns
         no_eqns       = length qs
@@ -85,7 +86,7 @@ The next two functions create the warning message.
 dsShadowWarn :: DsMatchContext -> [EquationInfo] -> DsM ()
 dsShadowWarn ctx@(DsMatchContext kind _ _) qs = dsWarn warn 
        where
-         warn | length qs > maximum_output
+         warn | qs `lengthExceeds` maximum_output
                = pp_context ctx (ptext SLIT("are overlapped"))
                            (\ f -> vcat (map (ppr_eqn f kind) (take maximum_output qs)) $$
                            ptext SLIT("..."))
@@ -103,8 +104,8 @@ dsIncompleteWarn ctx@(DsMatchContext kind _ _) pats = dsWarn warn
                                                  (take maximum_output pats))
                                      $$ dots))
 
-         dots | length pats > maximum_output = ptext SLIT("...")
-              | otherwise                    = empty
+         dots | pats `lengthExceeds` maximum_output = ptext SLIT("...")
+              | otherwise                           = empty
 
 pp_context NoMatchContext msg rest_of_msg_fun
   = dontAddErrLoc (ptext SLIT("Some match(es)") <+> hang msg 8 (rest_of_msg_fun id))
index 12b6f29..2bee279 100644 (file)
@@ -538,10 +538,10 @@ schemeT d s p app
    | let isVoidRepAtom (_, AnnVar v)    = VoidRep == typePrimRep (idType v)
          isVoidRepAtom (_, AnnNote n e) = isVoidRepAtom e
      in  is_con_call && isUnboxedTupleCon con 
-         && ( (length args_r_to_l == 2 && isVoidRepAtom (last (args_r_to_l)))
-              || (length args_r_to_l == 1)
+         && ( (args_r_to_l `lengthIs` 2 && isVoidRepAtom (last (args_r_to_l)))
+              || (isSingleton args_r_to_l) )
             )
-   = --trace (if length args_r_to_l == 1
+   = --trace (if isSingleton args_r_to_l
      --       then "schemeT: unboxed singleton"
      --       else "schemeT: unboxed pair with Void first component") (
      schemeT d s p (head args_r_to_l)
@@ -863,12 +863,12 @@ maybe_getCCallReturnRep :: Type -> Maybe PrimRep
 maybe_getCCallReturnRep fn_ty
    = let (a_tys, r_ty) = splitRepFunTys fn_ty
          maybe_r_rep_to_go  
-            = if length r_reps == 1 then Nothing else Just (r_reps !! 1)
+            = if isSingleton r_reps then Nothing else Just (r_reps !! 1)
          (r_tycon, r_reps) 
             = case splitTyConApp_maybe (repType r_ty) of
                       (Just (tyc, tys)) -> (tyc, map typePrimRep tys)
                       Nothing -> blargh
-         ok = ( (length r_reps == 2 && VoidRep == head r_reps)
+         ok = ( ( r_reps `lengthIs` 2 && VoidRep == head r_reps)
                 || r_reps == [VoidRep] )
               && isUnboxedTupleTyCon r_tycon
               && case maybe_r_rep_to_go of
index e7af9dc..7843943 100644 (file)
@@ -48,7 +48,7 @@ import Type           ( Kind, eqKind )
 import BasicTypes      ( Arity )
 import FiniteMap       ( lookupFM )
 import CostCentre
-import Util            ( eqListBy )
+import Util            ( eqListBy, lengthIs )
 import Outputable
 \end{code}
 
@@ -159,7 +159,7 @@ toUfApp (Var v) as
                -> UfTuple (mk_hs_tup_con tc dc) tup_args
          where
            val_args  = dropWhile isTypeArg as
-           saturated = length val_args == idArity v
+           saturated = val_args `lengthIs` idArity v
            tup_args  = map toUfExpr val_args
            tc        = dataConTyCon dc
        ;
index 90a211f..113a048 100644 (file)
@@ -42,7 +42,7 @@ import FunDeps                ( pprFundeps )
 import Class           ( FunDep, DefMeth(..) )
 import CStrings                ( CLabelString )
 import Outputable      
-import Util            ( eqListBy )
+import Util            ( eqListBy, count )
 import SrcLoc          ( SrcLoc )
 import FastString
 
@@ -445,11 +445,17 @@ eq_cls_sig env (ClassOpSig n1 dm1 ty1 _) (ClassOpSig n2 dm2 ty2 _)
 countTyClDecls :: [TyClDecl name pat] -> (Int, Int, Int, Int, Int)
        -- class, data, newtype, synonym decls
 countTyClDecls decls 
- = (length [() | ClassDecl {} <- decls],
-    length [() | TySynonym {} <- decls],
-    length [() | IfaceSig  {} <- decls],
-    length [() | TyData {tcdND = DataType} <- decls],
-    length [() | TyData {tcdND = NewType} <- decls])
+ = (count isClassDecl     decls,
+    count isSynDecl       decls,
+    count isIfaceSigDecl  decls,
+    count isDataTy        decls,
+    count isNewTy         decls) 
+ where
+   isDataTy TyData{tcdND=DataType} = True
+   isDataTy _                      = False
+   
+   isNewTy TyData{tcdND=NewType} = True
+   isNewTy _                     = False
 \end{code}
 
 \begin{code}
index 49040bf..98207b6 100644 (file)
@@ -46,7 +46,7 @@ import PrelNames      ( mkTupConRdrName, listTyConKey, usOnceTyConKey, usManyTyConKey
                          usOnceTyConName, usManyTyConName
                        )
 import FiniteMap
-import Util            ( eqListBy )
+import Util            ( eqListBy, lengthIs )
 import Outputable
 \end{code}
 
@@ -341,7 +341,7 @@ toHsType ty@(TyConApp tc tys)       -- Must be saturated because toHsType's arg is of
   where
      generic_case = foldl HsAppTy (HsTyVar (getName tc)) tys'
      tys'         = map toHsType tys
-     saturated    = length tys == tyConArity tc
+     saturated    = tys `lengthIs` tyConArity tc
 
 toHsType ty@(ForAllTy _ _) = case tcSplitSigmaTy ty of
                                (tvs, preds, tau) -> HsForAllTy (Just (map toHsTyVar tvs))
index 4ff5945..9e7423d 100644 (file)
@@ -855,7 +855,7 @@ ilxFunAppArgs env num_sofar funty args tail_call known_clo
        = ([],[],env,args,funty)
     get_term_args n max args env funty
       | (case known_clo of
-           Just (_,_,needed,_) -> (length needed == n)
+           Just (_,_,needed,_) -> needed `lengthIs` n
            Nothing -> False)
        -- Stop if we have the optimal number for a direct call
        = ([],[],env,args,funty)
@@ -897,7 +897,7 @@ ilxFunAppArgs env num_sofar funty args tail_call known_clo
     -- the "callfunc" case.
     basic_call_instr =
       case known_clo of
-        Just (known_env,fun,needed,fvs) | (length needed == length now_args) && 
+        Just (known_env,fun,needed,fvs) | (equalLength needed now_args) && 
                                           all (\x -> elemIlxTyEnv x env) free_ilx_tvs -> 
            vcat [text "callclo class",
                  nameReference env (idName fun) <+> singleQuotes (ilxEnvQualifyByModule env (ppr fun)),
index 58d8808..9b5bcba 100644 (file)
@@ -66,6 +66,7 @@ import Outputable
 
 import Maybe
 import PrimOp
+import Util     ( lengthIs )
 
 #include "HsVersions.h"
 
@@ -266,7 +267,7 @@ javaCase :: (Expr -> Statement) -> CoreExpr -> Id -> [CoreAlt] -> [Statement]
 -- If we've got the wrong one, this is _|_, and the
 -- casting will catch this with an exception.
 
-javaCase r e x [(DataAlt d,bs,rhs)] | length bs > 0
+javaCase r e x [(DataAlt d,bs,rhs)] | not (null bs)
   = java_expr PushExpr e ++
     [ var [Final] (javaName x)
                  (whnf primRep (vmPOP (primRepToType primRep))) ] ++
@@ -420,7 +421,7 @@ javaApp r (CoreSyn.App f a) as
        | otherwise  = javaApp r f as
 javaApp r (CoreSyn.Var f) as 
   = case isDataConId_maybe f of {
-       Just dc | length as == dataConRepArity dc
+       Just dc | as `lengthIs` dataConRepArity dc
         -- NOTE: Saturated constructors never returning a primitive at this point
         --
         -- We push the arguments backwards, because we are using
index 5d3609c..dbd6bf1 100644 (file)
@@ -27,6 +27,7 @@ import Util           ( sortLt )
 import Outputable
 import CmdLineOpts     ( DynFlags(..), DynFlag(..), dopt )
 
+import List             ( replicate )
 import System          ( ExitCode(..), exitWith )
 import IO              ( hPutStr, hPutStrLn, stderr )
 \end{code}
@@ -161,5 +162,5 @@ dump hdr doc
           doc,
           text ""]
      where 
-        line = text (take 20 (repeat '='))
+        line = text (replicate 20 '=')
 \end{code}
index 773e6f5..b5085cd 100644 (file)
@@ -191,7 +191,7 @@ hscNoRecomp ghci_mode dflags have_object
       }}}
 
 compMsg use_object mod location =
-    mod_str ++ take (max 0 (16 - length mod_str)) (repeat ' ')
+    mod_str ++ replicate (max 0 (16 - length mod_str)) ' '
     ++" ( " ++ unJust "hscRecomp" (ml_hs_file location) ++ ", "
     ++ (if use_object
          then unJust "hscRecomp" (ml_obj_file location)
index 61eb47e..4f53d0a 100644 (file)
@@ -11,6 +11,7 @@ module HscStats ( ppSourceStats ) where
 import HsSyn
 import Outputable
 import Char            ( isSpace )
+import Util             ( count )
 \end{code}
 
 %************************************************************************
@@ -62,7 +63,7 @@ ppSourceStats short (HsModule name version exports imports decls _ src_loc)
     
     trim ls     = takeWhile (not.isSpace) (dropWhile isSpace ls)
 
-    fixity_ds   = length [() | FixD d <- decls]
+    fixity_ds   = count (\ x -> case x of { FixD{} -> True; _ -> False}) decls
                -- NB: this omits fixity decls on local bindings and
                -- in class decls.  ToDo
 
@@ -71,12 +72,13 @@ ppSourceStats short (HsModule name version exports imports decls _ src_loc)
 
     inst_decls  = [d | InstD d <- decls]
     inst_ds     = length inst_decls
-    default_ds  = length [() | DefD _ <- decls]
+    default_ds  = count (\ x -> case x of { DefD{} -> True; _ -> False}) decls
     val_decls   = [d | ValD d <- decls]
 
     real_exports = case exports of { Nothing -> []; Just es -> es }
     n_exports           = length real_exports
-    export_ms           = length [() | IEModuleContents _ <- real_exports]
+    export_ms           = count (\ e -> case e of { IEModuleContents{} -> True;_ -> False})
+                         real_exports
     export_ds           = n_exports - export_ms
     export_all          = case exports of { Nothing -> 1; other -> 0 }
 
index 78bec0c..9c8827b 100644 (file)
@@ -1,7 +1,7 @@
 {-# OPTIONS -fno-warn-incomplete-patterns -optc-DNON_POSIX_SOURCE #-}
 
 -----------------------------------------------------------------------------
--- $Id: Main.hs,v 1.88 2001/10/22 13:45:15 simonmar Exp $
+-- $Id: Main.hs,v 1.89 2001/10/25 02:13:13 sof Exp $
 --
 -- GHC Driver program
 --
@@ -257,7 +257,7 @@ main =
        -- -ohi sanity checking
    ohi    <- readIORef v_Output_hi
    if (isJust ohi && 
-       (mode == DoMake || mode == DoInteractive || length srcs > 1))
+       (mode == DoMake || mode == DoInteractive || srcs `lengthExceeds` 1))
        then throwDyn (UsageError "-ohi can only be used when compiling a single source file")
        else do
 
@@ -267,7 +267,7 @@ main =
 
        -- -o sanity checking
    o_file <- readIORef v_Output_file
-   if (length srcs > 1 && isJust o_file && mode /= DoLink && mode /= DoMkDLL)
+   if (srcs `lengthExceeds` 1 && isJust o_file && mode /= DoLink && mode /= DoMkDLL)
        then throwDyn (UsageError "can't apply -o to multiple source files")
        else do
 
index d672241..d01b25f 100644 (file)
@@ -153,7 +153,7 @@ pcPrimTyCon name arg_vrcs rep
   = mkPrimTyCon name kind arity arg_vrcs rep
   where
     arity       = length arg_vrcs
-    kind        = mkArrowKinds (take arity (repeat liftedTypeKind)) result_kind
+    kind        = mkArrowKinds (replicate arity liftedTypeKind) result_kind
     result_kind = unliftedTypeKind -- all primitive types are unlifted
 
 pcPrimTyCon0 :: Name -> PrimRep -> TyCon
index 310e36e..4eb977d 100644 (file)
@@ -21,7 +21,7 @@ import CoreSyn
 import VarEnv  
 import CoreLint                ( showPass, endPass )
 import Outputable
-import Util            ( mapAccumL )
+import Util            ( mapAccumL, lengthExceeds )
 import UniqFM
 \end{code}
 
@@ -227,7 +227,7 @@ extendCSEnv (CS cs in_scope sub) id expr
   = CS (addToUFM_C combine cs hash [(id, expr)]) in_scope sub
   where
     hash   = hashExpr expr
-    combine old new = WARN( length result > 4, text "extendCSEnv: long list:" <+> ppr result )
+    combine old new = WARN( result `lengthExceeds` 4, text "extendCSEnv: long list:" <+> ppr result )
                      result
                    where
                      result = new ++ old
index f14a011..be854af 100644 (file)
@@ -25,7 +25,7 @@ import Id             ( isOneShotLambda )
 import Var             ( Id, idType, isTyVar )
 import Type            ( isUnLiftedType )
 import VarSet
-import Util            ( zipEqual, zipWithEqual )
+import Util            ( zipEqual, zipWithEqual, count )
 import Outputable
 \end{code}
 
@@ -424,7 +424,7 @@ sepBindsByDropPoint is_case drop_pts floaters
                --        E -> ...not mentioning x...
 
          n_alts      = length used_in_flags
-         n_used_alts = length [() | True <- used_in_flags]
+         n_used_alts = count id used_in_flags -- returns number of Trues in list.
 
          can_push = n_used_alts == 1           -- Used in just one branch
                   || (is_case &&               -- We are looking at case alternatives
index 7c3f243..0df2551 100644 (file)
@@ -179,7 +179,7 @@ saTransform binder rhs
     case r of
       -- [Andre] test: do it only if we have more than one static argument.
       --Just (tyargs,args) | any isStatic args
-      Just (tyargs,args) | length (filter isStatic args) > 1
+      Just (tyargs,args) | (filter isStatic args) `lengthExceeds` 1
        -> newSATName binder (new_ty tyargs args)  `thenSAT` \ binder' ->
           mkNewRhs binder binder' tyargs args rhs `thenSAT` \ new_rhs ->
           trace ("SAT "++ show (length (filter isStatic args))) (
@@ -240,10 +240,12 @@ saTransform binder rhs
 
        -- now, we drop the ones that are
        -- static, that is, the ones we will not pass to the local function
-       l            = length dict_tys
        tv_tmpl'     = dropStatics tyargs tv_tmpl
-       dict_tys'    = dropStatics (take l args) dict_tys
-       reg_arg_tys' = dropStatics (drop l args) reg_arg_tys
+
+       (args1, args2) = splitAtList dict_tys args
+       dict_tys'    = dropStatics args1 dict_tys
+       reg_arg_tys' = dropStatics args2 reg_arg_tys
+
        tau_ty'      = glueTyArgs reg_arg_tys' res_type
 
        mk_inst_tyenv []                    _ = emptyVarEnv
index 46e8b4f..86fb305 100644 (file)
@@ -18,6 +18,7 @@ import BasicTypes     ( TopLevelFlag(..), isTopLevel )
 import Util            ( mapAccumL )
 
 #ifdef DEBUG
+import Util            ( lengthIs )
 import Outputable
 #endif
 \end{code}
@@ -202,7 +203,7 @@ constructSRT caf_refs sub_srt initial_offset current_offset
        srt_info | srt_length == 0 = NoSRT
                | otherwise       = SRT initial_offset srt_length
 
-   in ASSERT( srt_length == length this_srt )
+   in ASSERT( this_srt `lengthIs` srt_length )
       (srt_info, this_srt, new_offset)
 \end{code}
 
index f806be1..9e27df4 100644 (file)
@@ -505,7 +505,7 @@ ruleCheckProgram phase rule_pat binds
         ]
   where
     results = unionManyBags (map (ruleCheckBind (phase, rule_pat)) binds)
-    line = text (take 20 (repeat '-'))
+    line = text (replicate 20 '-')
          
 type RuleCheckEnv = (CompilerPhase, String)    -- Phase and Pattern
 
index 32132c7..824b1e5 100644 (file)
@@ -32,7 +32,7 @@ import BasicTypes     ( Activation(..) )
 import Outputable
 
 import Maybes          ( orElse )
-import Util            ( mapAccumL )
+import Util            ( mapAccumL, lengthAtLeast )
 import List            ( nubBy, partition )
 import UniqSupply
 import Outputable
@@ -432,7 +432,7 @@ specialise env fn bndrs body (SCU {calls=calls, occs=occs})
        good_calls :: [[CoreArg]]
        good_calls = [ pats
                     | (con_env, call_args) <- all_calls,
-                      length call_args >= n_bndrs,         -- App is saturated
+                      call_args `lengthAtLeast` n_bndrs,           -- App is saturated
                       let call = (bndrs `zip` call_args),
                       any (good_arg con_env occs) call,    -- At least one arg is a constr app
                       let (_, pats) = argsToPats con_env us call_args
@@ -565,7 +565,7 @@ is_con_app_maybe env (Lit lit)
 is_con_app_maybe env expr
   = case collectArgs expr of
        (Var fun, args) | Just con <- isDataConId_maybe fun,
-                         length args >= dataConRepArity con
+                         args `lengthAtLeast` dataConRepArity con
                -- Might be > because the arity excludes type args
                        -> Just (DataAlt con,args)
 
index 0428772..746814f 100644 (file)
@@ -40,7 +40,8 @@ import ErrUtils               ( dumpIfSet_dyn )
 import BasicTypes      ( Activation( AlwaysActive ) )
 import Bag
 import List            ( partition )
-import Util            ( zipEqual, zipWithEqual, cmpList )
+import Util            ( zipEqual, zipWithEqual, cmpList, lengthIs,
+                         equalLength, lengthAtLeast )
 import Outputable
 
 
@@ -785,8 +786,8 @@ specDefn :: Subst                   -- Subst to use for RHS
 
 specDefn subst calls (fn, rhs)
        -- The first case is the interesting one
-  |  n_tyvars == length rhs_tyvars     -- Rhs of fn's defn has right number of big lambdas
-  && n_dicts  <= length rhs_bndrs      -- and enough dict args
+  |  rhs_tyvars `lengthIs` n_tyvars    -- Rhs of fn's defn has right number of big lambdas
+  && rhs_bndrs  `lengthAtLeast` n_dicts        -- and enough dict args
   && not (null calls_for_me)           -- And there are some calls to specialise
   && not (isDataConWrapId fn)          -- And it's not a data con wrapper, which have
                                        -- stupid overloading that simply discard the dictionary
@@ -848,7 +849,7 @@ specDefn subst calls (fn, rhs)
                        UsageDetails,                   -- Usage details from specialised body
                        CoreRule)                       -- Info for the Id's SpecEnv
     spec_call (CallKey call_ts, (call_ds, call_fvs))
-      = ASSERT( length call_ts == n_tyvars && length call_ds == n_dicts )
+      = ASSERT( call_ts `lengthIs` n_tyvars  && call_ds `lengthIs` n_dicts )
                -- Calls are only recorded for properly-saturated applications
        
        -- Suppose f's defn is  f = /\ a b c d -> \ d1 d2 -> rhs        
@@ -910,8 +911,8 @@ specDefn subst calls (fn, rhs)
 
       where
        my_zipEqual doc xs ys 
-        | length xs /= length ys = pprPanic "my_zipEqual" (ppr xs $$ ppr ys $$ (ppr fn <+> ppr call_ts) $$ ppr rhs)
-        | otherwise              = zipEqual doc xs ys
+        | not (equalLength xs ys) = pprPanic "my_zipEqual" (ppr xs $$ ppr ys $$ (ppr fn <+> ppr call_ts) $$ ppr rhs)
+        | otherwise               = zipEqual doc xs ys
 
 dropInline :: CoreExpr -> (Bool, CoreExpr) 
 dropInline (Note InlineMe rhs) = (True, rhs)
@@ -1004,8 +1005,8 @@ callDetailsToList calls = [ (id,tys,dicts)
 
 mkCallUDs subst f args 
   | null theta
-  || length spec_tys /= n_tyvars
-  || length dicts    /= n_dicts
+  || not (spec_tys `lengthIs` n_tyvars)
+  || not ( dicts   `lengthIs` n_dicts)
   || maybeToBool (lookupRule (\act -> True) (substInScope subst) f args)
        -- There's already a rule covering this call.  A typical case
        -- is where there's an explicit user-provided rule.  Then
index c99c76f..38c9c4d 100644 (file)
@@ -35,6 +35,7 @@ import OccName                ( occNameUserString )
 import BasicTypes       ( TopLevelFlag(..), isNotTopLevel, Arity )
 import CmdLineOpts     ( DynFlags, opt_RuntimeTypes )
 import FastTypes       hiding ( fastOr )
+import Util             ( listLengthCmp )
 import Outputable
 
 infixr 9 `thenLne`
@@ -305,7 +306,7 @@ to do it before the SRT pass to save the SRT entries associated with
 any top-level PAPs.
 
 \begin{code}
-isPAP (StgApp f args) = idArity f > length args
+isPAP (StgApp f args) = listLengthCmp args (idArity f) == LT -- idArity f > length args
 isPAP _              = False
 \end{code}
 
index 3692e06..b36c5b0 100644 (file)
@@ -23,7 +23,7 @@ import Type           ( mkFunTys, splitFunTys, splitTyConApp_maybe,
                          isUnLiftedType, isTyVarTy, splitForAllTys, Type
                        )
 import TyCon           ( TyCon, isDataTyCon, tyConDataCons )
-import Util            ( zipEqual )
+import Util            ( zipEqual, equalLength )
 import Outputable
 
 infixr 9 `thenL`, `thenL_`, `thenMaybeL`, `thenMaybeL_`
@@ -261,7 +261,7 @@ lintAlgAlt scrut_ty (con, args, _, rhs)
                -- This almost certainly does not work for existential constructors
         in
         checkL (con `elem` cons) (mkAlgAltMsg2 scrut_ty con) `thenL_`
-        checkL (length arg_tys == length args) (mkAlgAltMsg3 con args)
+        checkL (equalLength arg_tys args) (mkAlgAltMsg3 con args)
                                                                 `thenL_`
         mapL check (zipEqual "lintAlgAlt:stg" arg_tys args)     `thenL_`
         returnL ()
index d1ceb30..d0ac19e 100644 (file)
@@ -31,7 +31,7 @@ import UniqFM         ( plusUFM_C, addToUFM_Directly, lookupUFM_Directly,
                          keysUFM, minusUFM, ufmToList, filterUFM )
 import Type            ( isUnLiftedType )
 import CoreLint                ( showPass, endPass )
-import Util            ( mapAndUnzip, mapAccumL, mapAccumR )
+import Util            ( mapAndUnzip, mapAccumL, mapAccumR, lengthIs, equalLength )
 import BasicTypes      ( Arity, TopLevelFlag(..), isTopLevel, isNeverActive )
 import Maybes          ( orElse, expectJust )
 import Outputable
@@ -667,7 +667,7 @@ dmdTransform sigs var dmd
                -- ds can be empty, when we are just seq'ing the thing
                -- If so we must make up a suitable bunch of demands
           dmd_ds | null ds   = replicate arity Abs
-                 | otherwise = ASSERT( length ds == arity ) ds
+                 | otherwise = ASSERT( ds `lengthIs` arity ) ds
 
           arg_ds = case k of
                        Keep  -> bothLazy_s dmd_ds
@@ -831,13 +831,13 @@ bothRes r1 r2     = r1
 -- A Seq can have an empty list of demands, in the polymorphic case.
 lubs [] ds2 = ds2
 lubs ds1 [] = ds1
-lubs ds1 ds2 = ASSERT( length ds1 == length ds2 ) zipWith lub ds1 ds2
+lubs ds1 ds2 = ASSERT( equalLength ds1 ds2 ) zipWith lub ds1 ds2
 
 -----------------------------------
 -- A Seq can have an empty list of demands, in the polymorphic case.
 boths [] ds2  = ds2
 boths ds1 []  = ds1
-boths ds1 ds2 = ASSERT( length ds1 == length ds2 ) zipWith both ds1 ds2
+boths ds1 ds2 = ASSERT( equalLength ds1 ds2 ) zipWith both ds1 ds2
 \end{code}
 
 \begin{code}
index 14bb2df..f534371 100644 (file)
@@ -35,7 +35,7 @@ import Type           ( splitTyConApp_maybe,
                          isUnLiftedType, Type )
 import TyCon           ( tyConUnique )
 import PrelInfo                ( numericTyKeys )
-import Util            ( isIn, nOfThem, zipWithEqual )
+import Util            ( isIn, nOfThem, zipWithEqual, equalLength )
 import Outputable      
 \end{code}
 
@@ -294,7 +294,7 @@ evalStrictness (WwUnpack _ demand_info) val
       AbsTop      -> False
       AbsBot      -> True
       AbsProd vals
-          | length vals /= length demand_info -> pprTrace "TELL SIMON: evalStrictness" (ppr demand_info $$ ppr val)
+          | not (equalLength vals demand_info) -> pprTrace "TELL SIMON: evalStrictness" (ppr demand_info $$ ppr val)
                                                  False
           | otherwise -> or (zipWithEqual "evalStrictness" evalStrictness demand_info vals)
 
@@ -323,7 +323,7 @@ evalAbsence (WwUnpack _ demand_info) val
        AbsTop       -> False           -- No poison in here
        AbsBot       -> True            -- Pure poison
        AbsProd vals 
-          | length vals /= length demand_info -> pprTrace "TELL SIMON: evalAbsence" (ppr demand_info $$ ppr val)
+          | not (equalLength vals demand_info) -> pprTrace "TELL SIMON: evalAbsence" (ppr demand_info $$ ppr val)
                                                  True
           | otherwise -> or (zipWithEqual "evalAbsence" evalAbsence demand_info vals)
        _              -> pprTrace "TELL SIMON: evalAbsence" 
@@ -464,7 +464,7 @@ absEval anal expr@(Case scrut case_bndr alts) env
                -- type; so the constructor in this alternative must be the right one
                -- so we can go ahead and bind the constructor args to the components
                -- of the product value.
-           ASSERT(length arg_vals == length val_bndrs)
+           ASSERT(equalLength arg_vals val_bndrs)
            absEval anal rhs rhs_env
          where
            val_bndrs = filter isId bndrs
index 666d7ff..fce4fbd 100644 (file)
@@ -22,7 +22,7 @@ import ErrUtils               ( dumpIfSet_dyn )
 import SaAbsInt
 import SaLib
 import Demand          ( Demand, wwStrict, isStrict, isLazy )
-import Util            ( zipWith3Equal, stretchZipWith )
+import Util            ( zipWith3Equal, stretchZipWith, compareLength )
 import BasicTypes      ( Activation( NeverActive ) )
 import Outputable
 import FastTypes
@@ -233,7 +233,9 @@ saApp str_env abs_env (fun, args)
   where
     arg_dmds = case fun of
                 Var var -> case lookupAbsValEnv str_env var of
-                               Just (AbsApproxFun ds _) | length ds >= length args 
+                               Just (AbsApproxFun ds _) 
+                                  | compareLength ds args /= LT 
+                                             -- 'ds' is at least as long as 'args'.
                                        -> ds ++ minDemands
                                other   -> minDemands
                 other -> minDemands
index 159dd8f..03f4e56 100644 (file)
@@ -28,6 +28,7 @@ import BasicTypes     ( RecFlag(..), isNonRec, Activation(..) )
 import Maybes          ( orElse )
 import CmdLineOpts
 import WwLib
+import Util            ( lengthIs )
 import Outputable
 \end{code}
 
@@ -226,7 +227,7 @@ tryWW is_rec fn_id rhs
 
 ---------------------
 splitFun fn_id fn_info wrap_dmds res_info inline_prag rhs
-  = WARN( arity /= length wrap_dmds, ppr fn_id <+> (ppr arity $$ ppr wrap_dmds $$ ppr res_info) )
+  = WARN( not (wrap_dmds `lengthIs` arity), ppr fn_id <+> (ppr arity $$ ppr wrap_dmds $$ ppr res_info) )
        -- The arity should match the signature
     mkWwBodies fun_ty wrap_dmds res_info one_shots     `thenUs` \ (work_demands, wrap_fn, work_fn) ->
     getUniqueUs                                                `thenUs` \ work_uniq ->
index c16ba2c..a264e9c 100644 (file)
@@ -71,7 +71,7 @@ import VarEnv ( TidyEnv, lookupSubstEnv, SubstResult(..) )
 import VarSet  ( elemVarSet, emptyVarSet, unionVarSet )
 import TysWiredIn ( floatDataCon, doubleDataCon )
 import PrelNames( fromIntegerName, fromRationalName )
-import Util    ( thenCmp )
+import Util    ( thenCmp, equalLength )
 import Bag
 import Outputable
 \end{code}
@@ -415,7 +415,7 @@ newMethodAtLoc inst_loc real_id tys
   =    -- Get the Id type and instantiate it at the specified types
     let
        (tyvars,rho)  = tcSplitForAllTys (idType real_id)
-       rho_ty        = ASSERT( length tyvars == length tys )
+       rho_ty        = ASSERT( equalLength tyvars tys )
                        substTy (mkTopTyVarSubst tyvars tys) rho
        (theta, tau)  = tcSplitRhoTy rho_ty
     in
index e5a83ab..6c0ec03 100644 (file)
@@ -50,7 +50,7 @@ import NameSet
 import Var             ( tyVarKind )
 import VarSet
 import Bag
-import Util            ( isIn )
+import Util            ( isIn, equalLength )
 import BasicTypes      ( TopLevelFlag(..), RecFlag(..), isNonRec, isNotTopLevel,
                          isAlwaysActive )
 import FiniteMap       ( listToFM, lookupFM )
@@ -471,12 +471,11 @@ checkSigsCtxts sigs@(TySigInfo _ id1 sig_tvs theta1 _ _ _ src_loc : other_sigs)
     returnTc (sig_avails, map instToId sig_dicts)
   where
     sig1_dict_tys = map mkPredTy theta1
-    n_sig1_theta  = length theta1
     sig_meths    = concat [insts | TySigInfo _ _ _ _ _ _ insts _ <- sigs]
 
     check_one sig@(TySigInfo _ id _ theta _ _ _ src_loc)
        = tcAddErrCtxt (sigContextsCtxt id1 id)                 $
-        checkTc (length theta == n_sig1_theta) sigContextsErr  `thenTc_`
+        checkTc (equalLength theta theta1) sigContextsErr      `thenTc_`
         unifyTauTyLists sig1_dict_tys (map mkPredTy theta)
 
 checkSigsTyVars sigs = mapTc_ check_one sigs
index 90b17fd..82d5ebb 100644 (file)
@@ -53,7 +53,7 @@ import Var            ( TyVar )
 import VarSet          ( mkVarSet, emptyVarSet )
 import CmdLineOpts
 import ErrUtils                ( dumpIfSet )
-import Util            ( count )
+import Util            ( count, isSingleton, lengthIs, equalLength )
 import Maybes          ( seqMaybe, maybeToBool )
 \end{code}
 
@@ -122,7 +122,7 @@ tcClassDecl1 rec_env
        -- The renamer has already checked that the context mentions
        -- only the type variable of the class decl.
        -- Context is already kind-checked
-    ASSERT( length context == length sc_sel_names )
+    ASSERT( equalLength context sc_sel_names )
     tcHsTheta context                                          `thenTc` \ sc_theta ->
 
        -- CHECK THE CLASS SIGNATURES,
@@ -193,7 +193,7 @@ checkDefaultBinds clas ops (Just mbs)
       where
        n_generic    = count (maybeToBool . maybeGenericMatch) matches
        none_generic = n_generic == 0
-       all_generic  = n_generic == length matches
+       all_generic  = matches `lengthIs` n_generic
 \end{code}
 
 
@@ -262,7 +262,7 @@ checkValidClass cls
     doptsTc Opt_GlasgowExts                            `thenTc` \ gla_exts ->
 
        -- Check that the class is unary, unless GlaExs
-    checkTc (arity > 0)                (nullaryClassErr cls)   `thenTc_`
+    checkTc (not (null tyvars))                (nullaryClassErr cls)   `thenTc_`
     checkTc (gla_exts || unary) (classArityErr cls)    `thenTc_`
 
        -- Check the super-classes
@@ -278,8 +278,7 @@ checkValidClass cls
 
   where
     (tyvars, theta, _, op_stuff) = classBigSig cls
-    arity      = length tyvars
-    unary      = arity == 1
+    unary      = isSingleton tyvars
     no_generics = null [() | (_, GenDefMeth) <- op_stuff]
 
     check_op (sel_id, dm) 
index cb57efd..2e984fe 100644 (file)
@@ -283,9 +283,8 @@ tcMonoExpr e0@(HsCCall lbl args may_gc is_casm ignored_fake_result_ty) res_ty
     in
 
        -- Arguments
-    let n_args = length args
-       tv_idxs | n_args == 0 = []
-               | otherwise   = [1..n_args]
+    let tv_idxs | null args  = []
+               | otherwise  = [1..length args]
     in
     newTyVarTys (length tv_idxs) openTypeKind          `thenNF_Tc` \ arg_tys ->
     tcMonoExprs args arg_tys                           `thenTc`    \ (args', args_lie) ->
@@ -704,9 +703,12 @@ checkArgsCtxt fun args expected_res_ty actual_res_ty tidy_env
       (exp_args, _)    = tcSplitFunTys exp_ty''
       (act_args, _)    = tcSplitFunTys act_ty''
 
-      message | length exp_args < length act_args = wrongArgsCtxt "too few" fun args
-              | length exp_args > length act_args = wrongArgsCtxt "too many" fun args
-             | otherwise                         = appCtxt fun args
+      len_act_args     = length act_args
+      len_exp_args     = length exp_args
+
+      message | len_exp_args < len_act_args = wrongArgsCtxt "too few" fun args
+              | len_exp_args > len_act_args = wrongArgsCtxt "too many" fun args
+             | otherwise                   = appCtxt fun args
     in
     returnNF_Tc (env2, message)
 
@@ -896,7 +898,7 @@ missingFields rbinds data_con
 
     field_info = zipEqual "missingFields"
                          field_labels
-                         (drop (length ex_theta) (dataConStrictMarks data_con))
+                         (dropList ex_theta (dataConStrictMarks data_con))
        -- The 'drop' is because dataConStrictMarks
        -- includes the existential dictionaries
     (_, _, _, ex_theta, _, _) = dataConSig data_con
index 273572b..eafae42 100644 (file)
@@ -57,7 +57,7 @@ import TcType         ( isUnLiftedType, tcEqType, Type )
 import TysPrim         ( charPrimTy, intPrimTy, wordPrimTy, addrPrimTy,
                          floatPrimTy, doublePrimTy
                        )
-import Util            ( mapAccumL, zipEqual, zipWithEqual,
+import Util            ( mapAccumL, zipEqual, zipWithEqual, isSingleton,
                          zipWith3Equal, nOfThem )
 import Panic           ( panic, assertPanic )
 import Maybes          ( maybeToBool, orElse )
@@ -351,7 +351,7 @@ gen_Ord_binds tycon
     cmp_eq =
        mk_FunMonoBind tycon_loc 
                       cmp_eq_RDR 
-                      (if null nonnullary_cons && (length nullary_cons == 1) then
+                      (if null nonnullary_cons && isSingleton nullary_cons then
                           -- catch this specially to avoid warnings
                           -- about overlapping patterns from the desugarer.
                          let 
@@ -363,7 +363,7 @@ gen_Ord_binds tycon
                       else
                          map pats_etc nonnullary_cons ++
                          -- leave out wildcards to silence desugarer.
-                         (if length tycon_data_cons == 1 then
+                         (if isSingleton tycon_data_cons then
                              []
                           else
                               [([WildPatIn, WildPatIn], default_rhs)]))
@@ -527,7 +527,7 @@ gen_Bounded_binds tycon
   = if isEnumerationTyCon tycon then
        min_bound_enum `AndMonoBinds` max_bound_enum
     else
-       ASSERT(length data_cons == 1)
+       ASSERT(isSingleton data_cons)
        min_bound_1con `AndMonoBinds` max_bound_1con
   where
     data_cons = tyConDataCons tycon
index cc7d9b6..b559686 100644 (file)
@@ -37,7 +37,7 @@ import Var            ( mkTyVar, tyVarKind )
 import Name            ( Name, nameIsLocalOrFrom )
 import ErrUtils                ( pprBagOfErrors )
 import Outputable      
-import Util            ( zipWithEqual )
+import Util            ( zipWithEqual, dropList, equalLength )
 import HscTypes                ( TyThing(..) )
 \end{code}
 
@@ -337,10 +337,10 @@ tcCoreAlt scrut_ty alt@(con, names, rhs)
        ex_tyvars'          = [mkTyVar name (tyVarKind tv) | (name,tv) <- names `zip` ex_tyvars] 
        ex_tys'             = mkTyVarTys ex_tyvars'
        arg_tys             = dataConArgTys con (inst_tys ++ ex_tys')
-       id_names            = drop (length ex_tyvars) names
+       id_names            = dropList ex_tyvars names
        arg_ids
 #ifdef DEBUG
-               | length id_names /= length arg_tys
+               | not (equalLength id_names arg_tys)
                = pprPanic "tcCoreAlts" (ppr (con, names, rhs) $$
                                         (ppr main_tyvars <+> ppr ex_tyvars) $$
                                         ppr arg_tys)
@@ -348,7 +348,7 @@ tcCoreAlt scrut_ty alt@(con, names, rhs)
 #endif
                = zipWithEqual "tcCoreAlts" mkLocalId id_names arg_tys
     in
-    ASSERT( con `elem` tyConDataCons tycon && length inst_tys == length main_tyvars )
+    ASSERT( con `elem` tyConDataCons tycon && equalLength inst_tys main_tyvars )
     tcExtendTyVarEnv ex_tyvars'                        $
     tcExtendGlobalValEnv arg_ids               $
     tcCoreExpr rhs                                     `thenTc` \ rhs' ->
index aef778a..b992ce1 100644 (file)
@@ -66,6 +66,7 @@ import TysWiredIn     ( genericTyCons )
 import Name             ( Name )
 import SrcLoc           ( SrcLoc )
 import Unique          ( Uniquable(..) )
+import Util             ( lengthExceeds )
 import BasicTypes      ( NewOrData(..), Fixity )
 import ErrUtils                ( dumpIfSet_dyn )
 import ListSetOps      ( Assoc, emptyAssoc, plusAssoc_C, mapAssoc, 
@@ -348,7 +349,7 @@ get_generics decl@(ClassDecl {tcdName = class_name, tcdMeths = Just def_methods,
        tc_inst_infos = [(simpleInstInfoTyCon i, i) | i <- inst_infos]
 
        bad_groups = [group | group <- equivClassesByUniq get_uniq tc_inst_infos,
-                             length group > 1]
+                             group `lengthExceeds` 1]
        get_uniq (tc,_) = getUnique tc
     in
     mapTc (addErrTc . dupGenericInsts) bad_groups      `thenTc_`
index d5d394e..9d27e67 100644 (file)
@@ -88,7 +88,7 @@ import BasicTypes     ( Boxity, Arity, isBoxed )
 import CmdLineOpts     ( dopt, DynFlag(..) )
 import Unique          ( Uniquable(..) )
 import SrcLoc          ( noSrcLoc )
-import Util            ( nOfThem )
+import Util            ( nOfThem, isSingleton, equalLength )
 import ListSetOps      ( removeDups )
 import Outputable
 \end{code}
@@ -937,11 +937,11 @@ check_inst_head dflags clas tys
   = check_tyvars dflags clas tys
 
        -- WITH HASKELL 1.4, MUST HAVE C (T a b c)
-  | length tys == 1,
+  | isSingleton tys,
     Just (tycon, arg_tys) <- tcSplitTyConApp_maybe first_ty,
     not (isSynTyCon tycon),            -- ...but not a synonym
     all tcIsTyVarTy arg_tys,           -- Applied to type variables
-    length (varSetElems (tyVarsOfTypes arg_tys)) == length arg_tys
+    equalLength (varSetElems (tyVarsOfTypes arg_tys)) arg_tys
           -- This last condition checks that all the type variables are distinct
   = returnTc ()
 
@@ -1114,7 +1114,7 @@ uTys _ (FunTy fun1 arg1) _ (FunTy fun2 arg2)
 
        -- Type constructors must match
 uTys ps_ty1 (TyConApp con1 tys1) ps_ty2 (TyConApp con2 tys2)
-  | con1 == con2 && length tys1 == length tys2
+  | con1 == con2 && equalLength tys1 tys2
   = unifyTauTyLists tys1 tys2
 
   | con1 == openKindCon
index 518c4ff..4bbcc5a 100644 (file)
@@ -40,7 +40,9 @@ import NameSet
 import VarSet
 import Var             ( Id )
 import Bag
+import Util            ( isSingleton )
 import Outputable
+
 import List            ( nub )
 \end{code}
 
@@ -457,7 +459,7 @@ number of args are used in each equation.
 
 \begin{code}
 sameNoOfArgs :: [RenamedMatch] -> Bool
-sameNoOfArgs matches = length (nub (map args_in_match matches)) == 1
+sameNoOfArgs matches = isSingleton (nub (map args_in_match matches))
   where
     args_in_match :: RenamedMatch -> Int
     args_in_match (Match _ pats _ _) = length pats
index 41f0890..588f871 100644 (file)
@@ -642,12 +642,7 @@ type TcError   = Message
 type TcWarning = Message
 
 ctxt_to_use ctxt | opt_PprStyle_Debug = ctxt
-                | otherwise          = takeAtMost 3 ctxt
-                where
-                  takeAtMost :: Int -> [a] -> [a]
-                  takeAtMost 0 ls = []
-                  takeAtMost n [] = []
-                  takeAtMost n (x:xs) = x:takeAtMost (n-1) xs
+                | otherwise          = take 3 ctxt
 
 arityErr kind name n m
   = hsep [ text kind, quotes (ppr name), ptext SLIT("should have"),
index 867fa9d..c02e712 100644 (file)
@@ -61,7 +61,7 @@ import Name           ( Name )
 import TysWiredIn      ( mkListTy, mkTupleTy, genUnitTyCon )
 import BasicTypes      ( Boxity(..) )
 import SrcLoc          ( SrcLoc )
-import Util            ( isSingleton )
+import Util            ( isSingleton, lengthIs )
 import Outputable
 
 \end{code}
@@ -381,7 +381,7 @@ tc_type (HsListTy ty)
     returnTc (mkListTy tau_ty)
 
 tc_type (HsTupleTy (HsTupCon _ boxity arity) tys)
-  = ASSERT( arity == length tys )
+  = ASSERT( tys `lengthIs` arity )
     tc_types tys       `thenTc` \ tau_tys ->
     returnTc (mkTupleTy boxity arity tau_tys)
 
index c4cca7e..7f4e0df 100644 (file)
@@ -134,7 +134,7 @@ import PrelNames    -- Lots (e.g. in isFFIArgumentTy)
 import TysWiredIn      ( ptrTyCon, funPtrTyCon, addrTyCon, unitTyCon )
 import Unique          ( Unique, Uniquable(..) )
 import SrcLoc          ( SrcLoc )
-import Util            ( cmpList, thenCmp )
+import Util            ( cmpList, thenCmp, equalLength )
 import Maybes          ( maybeToBool, expectJust )
 import Outputable
 \end{code}
@@ -857,7 +857,7 @@ uTysX (FunTy fun1 arg1) (FunTy fun2 arg2) k subst
 
        -- Type constructors must match
 uTysX (TyConApp con1 tys1) (TyConApp con2 tys2) k subst
-  | (con1 == con2 && length tys1 == length tys2)
+  | (con1 == con2 && equalLength tys1 tys2)
   = uTyListsX tys1 tys2 k subst
 
        -- Applications need a bit of care!
index 1fe3575..e8d26d5 100644 (file)
@@ -34,8 +34,9 @@ import TysWiredIn       ( genericTyCons,
 import IdInfo           ( noCafNoTyGenIdInfo, setUnfoldingInfo )
 import CoreUnfold       ( mkTopUnfolding ) 
 
-import Unique          ( mkBuiltinUnique )
 import SrcLoc          ( builtinSrcLoc )
+import Unique          ( mkBuiltinUnique )
+import Util             ( takeList )
 import Outputable 
 
 #include "HsVersions.h"
@@ -517,7 +518,7 @@ bimapTuple eps
   = EP { fromEP = mk_hs_lam [tuple_pat] from_body,
         toEP   = mk_hs_lam [tuple_pat] to_body }
   where
-    names      = take (length eps) genericNames
+    names      = takeList eps genericNames
     tuple_pat  = TuplePatIn (map VarPatIn names) Boxed
     eps_w_names = eps `zip` names
     to_body     = ExplicitTuple [toEP   ep `HsApp` HsVar g | (ep,g) <- eps_w_names] Boxed
index f191fda..22b60bf 100644 (file)
@@ -37,6 +37,7 @@ import Maybes         ( maybeToBool )
 import Name            ( getOccString, getOccName )
 import Outputable
 import Unique          ( Uniquable(..) )
+import Util             ( lengthIs )
 import BasicTypes      ( tupleParens )
 import PrelNames               -- quite a few *Keys
 \end{code}
@@ -136,7 +137,7 @@ ppr_ty ctxt_prec ty@(TyConApp tycon tys)
        
        -- TUPLE CASE (boxed and unboxed)
   |  isTupleTyCon tycon,
-     length tys == tyConArity tycon    -- No magic if partially applied
+      tys `lengthIs` tyConArity tycon  -- No magic if partially applied
   = tupleParens (tupleTyConBoxity tycon)
                (sep (punctuate comma (map (ppr_ty tOP_PREC) tys)))
 
index eb77346..5ede243 100644 (file)
@@ -64,6 +64,7 @@ import BasicTypes     ( Arity, RecFlag(..), Boxity(..),
 import Name            ( Name, nameUnique, NamedThing(getName) )
 import PrelNames       ( Unique, Uniquable(..), anyBoxConKey )
 import PrimRep         ( PrimRep(..), isFollowableRep )
+import Util             ( lengthIs )
 import Outputable
 import FastString
 \end{code}
@@ -439,7 +440,7 @@ isForeignTyCon other                                      = False
 
 \begin{code}
 tyConDataCons :: TyCon -> [DataCon]
-tyConDataCons tycon = ASSERT2( length cons == tyConFamilySize tycon, ppr tycon )
+tyConDataCons tycon = ASSERT2( cons `lengthIs` (tyConFamilySize tycon), ppr tycon )
                      cons
                    where
                      cons = tyConDataConsIfAvailable tycon
index eb159f7..925357f 100644 (file)
@@ -109,7 +109,7 @@ import Maybes               ( maybeToBool )
 import SrcLoc          ( noSrcLoc )
 import PrimRep         ( PrimRep(..) )
 import Unique          ( Uniquable(..) )
-import Util            ( mapAccumL, seqList )
+import Util            ( mapAccumL, seqList, lengthIs )
 import Outputable
 import UniqSet         ( sizeUniqSet )         -- Should come via VarSet
 \end{code}
@@ -326,7 +326,7 @@ mkTyConApp tycon tys
 
   | isNewTyCon tycon,                  -- A saturated newtype application;
     not (isRecursiveTyCon tycon),      -- Not recursive (we don't use SourceTypes for them)
-    length tys == tyConArity tycon     -- use the SourceType form
+    tys `lengthIs` tyConArity tycon     -- use the SourceType form
   = SourceTy (NType tycon tys)
 
   | otherwise
@@ -372,7 +372,7 @@ mkSynTy tycon tys
   | n_args == arity    -- Exactly saturated
   = mk_syn tys
   | n_args >  arity    -- Over-saturated
-  = foldl AppTy (mk_syn (take arity tys)) (drop arity tys)
+  = case splitAt arity tys of { (as,bs) -> foldl AppTy (mk_syn as) bs }
   | otherwise          -- Un-saturated
   = TyConApp tycon tys
        -- For the un-saturated case we build TyConApp directly
@@ -426,7 +426,7 @@ repType (ForAllTy _ ty)   = repType ty
 repType (NoteTy   _ ty)   = repType ty
 repType (SourceTy  p)     = repType (sourceTypeRep p)
 repType (UsageTy  _ ty)   = repType ty
-repType (TyConApp tc tys) | isNewTyCon tc && length tys == tyConArity tc
+repType (TyConApp tc tys) | isNewTyCon tc && tys `lengthIs` tyConArity tc
                          = repType (newTypeRep tc tys)
 repType ty               = ty
 
@@ -650,7 +650,7 @@ splitNewType_maybe :: Type -> Maybe Type
 
 splitNewType_maybe ty
   = case splitTyConApp_maybe ty of
-       Just (tc,tys) | isNewTyCon tc -> ASSERT( length tys == tyConArity tc )
+       Just (tc,tys) | isNewTyCon tc -> ASSERT( tys `lengthIs` tyConArity tc )
                                                -- The assert should hold because repType should
                                                -- only be applied to *types* (of kind *)
                                         Just (newTypeRep tc tys)
@@ -880,7 +880,7 @@ isUnboxedTupleType ty = case splitTyConApp_maybe ty of
 -- Should only be applied to *types*; hence the assert
 isAlgType :: Type -> Bool
 isAlgType ty = case splitTyConApp_maybe ty of
-                       Just (tc, ty_args) -> ASSERT( length ty_args == tyConArity tc )
+                       Just (tc, ty_args) -> ASSERT( ty_args `lengthIs` tyConArity tc )
                                              isAlgTyCon tc
                        other              -> False
 \end{code}
@@ -911,7 +911,7 @@ isPrimitiveType :: Type -> Bool
 -- Most of these are unlifted, but now that we interact with .NET, we
 -- may have primtive (foreign-imported) types that are lifted
 isPrimitiveType ty = case splitTyConApp_maybe ty of
-                       Just (tc, ty_args) -> ASSERT( length ty_args == tyConArity tc )
+                       Just (tc, ty_args) -> ASSERT( ty_args `lengthIs` tyConArity tc )
                                              isPrimTyCon tc
                        other              -> False
 \end{code}
index 8be6654..cce3ffe 100644 (file)
@@ -32,6 +32,7 @@ import VarEnv
 import VarSet
 import UniqSupply       ( UniqSupply, UniqSM,
                           initUs, splitUniqSupply )
+import Util             ( lengthExceeds )
 import Outputable
 import Maybes           ( expectJust )
 import List             ( unzip4 )
@@ -477,7 +478,7 @@ pessimise ty
     pessN co ve     (NoteTy (FTVNote _)    ty) = pessN co ve ty
     pessN co ve     (TyVarTy _)                = emptyUConSet
     pessN co ve     (AppTy _ _)                = emptyUConSet
-    pessN co ve     (TyConApp tc tys)          = ASSERT( not((isFunTyCon tc)&&(length tys > 1)) )
+    pessN co ve     (TyConApp tc tys)          = ASSERT( not((isFunTyCon tc)&&( tys `lengthExceeds` 1)) )
                                                  emptyUConSet
     pessN co ve     (FunTy ty1 ty2)            = pess (not co) ve ty1 `unionUCS` pess co ve ty2
     pessN co ve     (ForAllTy _ ty)            = pessN co ve ty
index 0a18567..03efe52 100644 (file)
@@ -37,6 +37,7 @@ import TyCon            ( isAlgTyCon, isPrimTyCon, isSynTyCon, isFunTyCon )
 import VarEnv
 import PrimOp           ( PrimOp, primOpUsg )
 import UniqSupply       ( UniqSupply, UniqSM, initUs, getUniqueUs, thenUs, returnUs )
+import Util             ( lengthExceeds )
 import Outputable
 
 
@@ -431,7 +432,7 @@ pessimiseN co     (NoteTy      (SynNote sty) ty) = NoteTy (SynNote (pessimiseN c
 pessimiseN co     (NoteTy note@(FTVNote _  ) ty) = NoteTy note (pessimiseN co ty)
 pessimiseN co ty0@(TyVarTy _)                    = ty0
 pessimiseN co ty0@(AppTy _ _)                    = ty0
-pessimiseN co ty0@(TyConApp tc tys)              = ASSERT( not ((isFunTyCon tc) && (length tys > 1)) )
+pessimiseN co ty0@(TyConApp tc tys)              = ASSERT( not ((isFunTyCon tc) && (tys `lengthExceeds` 1)) )
                                                    ty0
 pessimiseN co     (FunTy ty1 ty2)                = FunTy (pessimise (not co) ty1)
                                                          (pessimise      co  ty2)
index 1544c7b..3fb9dd4 100644 (file)
@@ -211,7 +211,7 @@ drawTree         = unlines . draw
 draw (Node x ts) = grp this (space (length this)) (stLoop ts)
  where this          = s1 ++ x ++ " "
 
-       space n       = take n (repeat ' ')
+       space n       = replicate n ' '
 
        stLoop []     = [""]
        stLoop [t]    = grp s2 "  " (draw t)
index b1c93a8..51f53f3 100644 (file)
@@ -17,7 +17,9 @@ module Util (
        zipEqual, zipWithEqual, zipWith3Equal, zipWith4Equal,
         zipLazy, stretchZipWith,
        mapAndUnzip, mapAndUnzip3,
-       nOfThem, lengthExceeds, isSingleton, only,
+       nOfThem, 
+       lengthExceeds, lengthIs, lengthAtLeast, listLengthCmp, atLength,
+       isSingleton, only,
        snocView,
        isIn, isn'tIn,
 
@@ -39,9 +41,12 @@ module Util (
        -- accumulating
        mapAccumL, mapAccumR, mapAccumB, 
        foldl2, count,
+       
+       takeList, dropList, splitAtList,
 
        -- comparisons
-       eqListBy, thenCmp, cmpList, prefixMatch, suffixMatch,
+       eqListBy, equalLength, compareLength,
+       thenCmp, cmpList, prefixMatch, suffixMatch,
 
        -- strictness
        foldl', seqList,
@@ -228,10 +233,47 @@ mapAndUnzip3 f (x:xs)
 nOfThem :: Int -> a -> [a]
 nOfThem n thing = replicate n thing
 
+-- 'atLength atLen atEnd ls n' unravels list 'ls' to position 'n';
+-- specification:
+--
+--  atLength atLenPred atEndPred ls n
+--   | n < 0         = atLenPred n
+--   | length ls < n = atEndPred (n - length ls)
+--   | otherwise     = atLenPred (drop n ls)
+--
+atLength :: ([a] -> b)
+         -> (Int -> b)
+         -> [a]
+         -> Int
+         -> b
+atLength atLenPred atEndPred ls n 
+  | n < 0     = atEndPred n 
+  | otherwise = go n ls
+  where
+    go n [] = atEndPred n
+    go 0 ls = atLenPred ls
+    go n (_:xs) = go (n-1) xs
+
+-- special cases.
 lengthExceeds :: [a] -> Int -> Bool
--- (lengthExceeds xs n) is True if   length xs > n
-(x:xs) `lengthExceeds` n = n < 1 || xs `lengthExceeds` (n - 1)
-[]     `lengthExceeds` n = n < 0
+lengthExceeds = atLength (not.null) (const False)
+
+lengthAtLeast :: [a] -> Int -> Bool
+lengthAtLeast = atLength (not.null) (== 0)
+
+lengthIs :: [a] -> Int -> Bool
+lengthIs = atLength null (==0)
+
+listLengthCmp :: [a] -> Int -> Ordering 
+listLengthCmp = atLength atLen atEnd 
+ where
+  atEnd 0      = EQ
+  atEnd x
+   | x > 0     = LT -- not yet seen 'n' elts, so list length is < n.
+   | otherwise = GT
+
+  atLen []     = EQ
+  atLen _      = GT
 
 isSingleton :: [a] -> Bool
 isSingleton [x] = True
@@ -631,6 +673,32 @@ count p (x:xs) | p x       = 1 + count p xs
               | otherwise = count p xs
 \end{code}
 
+@splitAt@, @take@, and @drop@ but with length of another
+list giving the break-off point:
+
+\begin{code}
+takeList :: [b] -> [a] -> [a]
+takeList [] _ = []
+takeList (_:xs) ls = 
+   case ls of
+     [] -> []
+     (y:ys) -> y : takeList xs ys
+
+dropList :: [b] -> [a] -> [a]
+dropList [] xs    = xs
+dropList _  xs@[] = xs
+dropList (_:xs) (_:ys) = dropList xs ys
+
+
+splitAtList :: [b] -> [a] -> ([a], [a])
+splitAtList [] xs     = ([], xs)
+splitAtList _ xs@[]   = (xs, xs)
+splitAtList (_:xs) (y:ys) = (y:ys', ys'')
+    where
+      (ys', ys'') = splitAtList xs ys
+
+\end{code}
+
 
 %************************************************************************
 %*                                                                     *
@@ -644,6 +712,17 @@ eqListBy eq []     []     = True
 eqListBy eq (x:xs) (y:ys) = eq x y && eqListBy eq xs ys
 eqListBy eq xs     ys     = False
 
+equalLength :: [a] -> [b] -> Bool
+equalLength [] []         = True
+equalLength (_:xs) (_:ys) = equalLength xs ys
+equalLength xs    ys      = False
+
+compareLength :: [a] -> [b] -> Ordering
+compareLength [] []         = EQ
+compareLength (_:xs) (_:ys) = compareLength xs ys
+compareLength [] _ys        = LT
+compareLength _xs []        = GT
+
 thenCmp :: Ordering -> Ordering -> Ordering
 {-# INLINE thenCmp #-}
 thenCmp EQ   any = any