{-
(c) The University of Glasgow 2006
(c) The GRASP/AQUA Project, Glasgow University, 1992-1998
\section[ListSetOps]{Set-like operations on lists}
-}{-# LANGUAGE CPP #-}moduleListSetOps(unionLists ,minusList ,deleteBys ,-- Association listsAssoc ,assoc ,assocMaybe ,assocUsing ,assocDefault ,assocDefaultUsing ,-- Duplicate handlinghasNoDups ,removeDups ,findDupsEq ,equivClasses ,-- IndexinggetNth )where#include "HsVersions.h"
importGhcPrelude importOutputable importUtil importData.ListimportqualifiedData.List.NonEmptyasNEimportData.List.NonEmpty(NonEmpty(..))importqualifiedData.SetasSgetNth::Outputable a =>[a ]->Int->a getNth xs n =ASSERT2(xs `lengthExceeds`n ,ppr n $$ pprxs)xs !!n deleteBys::(a ->a ->Bool)->[a ]->[a ]->[a ]-- (deleteBys eq xs ys) returns xs-ys, using the given equality function-- Just like 'Data.List.delete' but with an equality functiondeleteBys eq xs ys =foldl'(flip(deleteByeq ))xs ys {-
************************************************************************
* *
 Treating lists as sets
 Assumes the lists contain no duplicates, but are unordered
* *
************************************************************************
-}unionLists::(Outputable a ,Eqa )=>[a ]->[a ]->[a ]-- Assumes that the arguments contain no duplicatesunionLists xs ys =WARN(lengthExceedsxs 100|| lengthExceedsys 100,pprxs$$pprys)[x |x <-xs ,isn'tIn "unionLists"x ys ]++ys -- | Calculate the set difference of two lists. This is-- /O((m + n) log n)/, where we subtract a list of /n/ elements-- from a list of /m/ elements.---- Extremely short cases are handled specially:-- When /m/ or /n/ is 0, this takes /O(1)/ time. When /m/ is 1,-- it takes /O(n)/ time.minusList::Orda =>[a ]->[a ]->[a ]-- There's no point building a set to perform just one lookup, so we handle-- extremely short lists specially. It might actually be better to use-- an O(m*n) algorithm when m is a little longer (perhaps up to 4 or even 5).-- The tipping point will be somewhere in the area of where /m/ and /log n/-- become comparable, but we probably don't want to work too hard on this.minusList []_=[]minusListxs @[x ]ys |x `elem`ys =[]|otherwise=xs -- Using an empty set or a singleton would also be silly, so let's not.minusListxs []=xs minusListxs [y ]=filter(/=y )xs -- When each list has at least two elements, we build a set from the-- second argument, allowing us to filter the first argument fairly-- efficiently.minusListxs ys =filter(`S.notMember`yss )xs whereyss =S.fromListys {-
************************************************************************
* *
\subsection[Utils-assoc]{Association lists}
* *
************************************************************************
Inefficient finite maps based on association lists and equality.
-}-- A finite mapping based on equality and association liststypeAssoc a b =[(a ,b )]assoc::(Eqa )=>String->Assoc a b ->a ->b assocDefault::(Eqa )=>b ->Assoc a b ->a ->b assocUsing::(a ->a ->Bool)->String->Assoc a b ->a ->b assocMaybe::(Eqa )=>Assoc a b ->a ->Maybeb assocDefaultUsing::(a ->a ->Bool)->b ->Assoc a b ->a ->b assocDefaultUsing _deflt []_=deflt assocDefaultUsingeq deflt ((k ,v ):rest )key |k `eq `key =v |otherwise=assocDefaultUsing eq deflt rest key assoc crash_msg list key =assocDefaultUsing (==)(panic ("Failed in assoc: "++crash_msg ))list key assocDefault deflt list key =assocDefaultUsing (==)deflt list key assocUsing eq crash_msg list key =assocDefaultUsing eq (panic ("Failed in assoc: "++crash_msg ))list key assocMaybe alist key =lookup alist wherelookup []=Nothinglookup((tv ,ty ):rest )=ifkey ==tv thenJustty elselookup rest {-
************************************************************************
* *
\subsection[Utils-dups]{Duplicate-handling}
* *
************************************************************************
-}hasNoDups::(Eqa )=>[a ]->BoolhasNoDups xs =f []xs wheref _[]=Truefseen_so_far (x :xs )=ifx `is_elem `seen_so_far thenFalseelsef (x :seen_so_far )xs is_elem =isIn "hasNoDups"equivClasses::(a ->a ->Ordering)-- Comparison->[a ]->[NonEmptya ]equivClasses _[]=[]equivClasses_[stuff ]=[stuff :|[]]equivClassescmp items =NE.groupByeq (sortBycmp items )whereeq a b =casecmp a b of{EQ->True;_->False}removeDups::(a ->a ->Ordering)-- Comparison function->[a ]->([a ],-- List with no duplicates[NonEmptya ])-- List of duplicate groups. One representative-- from each group appears in the first resultremoveDups _[]=([],[])removeDups_[x ]=([x ],[])removeDupscmp xs =case(mapAccumRcollect_dups [](equivClasses cmp xs ))of{(dups ,xs' )->(xs' ,dups )}wherecollect_dups::[NonEmptya ]->NonEmptya ->([NonEmptya ],a )collect_dups dups_so_far (x :|[])=(dups_so_far ,x )collect_dupsdups_so_far dups @(x :|_)=(dups :dups_so_far ,x )findDupsEq::(a ->a ->Bool)->[a ]->[NonEmptya ]findDupsEq _[]=[]findDupsEqeq (x :xs )|nulleq_xs =findDupsEq eq xs |otherwise=(x :|eq_xs ):findDupsEq eq neq_xs where(eq_xs ,neq_xs )=partition(eq x )xs 

AltStyle によって変換されたページ (->オリジナル) /