Movatterモバイル変換


[0]ホーム

URL:


\begin{code}
{-# LANGUAGE Trustworthy #-}{-# LANGUAGE NoImplicitPrelude, BangPatterns, MagicHash #-}{-# OPTIONS_HADDOCK hide #-}------------------------------------------------------------------------------- |-- Module      :  GHC.Enum-- Copyright   :  (c) The University of Glasgow, 1992-2002-- License     :  see libraries/base/LICENSE---- Maintainer  :  cvs-ghc@haskell.org-- Stability   :  internal-- Portability :  non-portable (GHC extensions)---- The 'Enum' and 'Bounded' classes.--------------------------------------------------------------------------------- #hidemoduleGHC.Enum(Bounded(..),Enum(..),boundedEnumFrom,boundedEnumFromThen,-- Instances for Bounded and Enum: (), Char, Int)whereimportGHC.BaseimportData.Tuple()-- for dependenciesdefault()-- Double isn't available yet
\end{code}%*********************************************************%* *\subsection{Class declarations}%* *%*********************************************************\begin{code}
-- | The 'Bounded' class is used to name the upper and lower limits of a-- type.  'Ord' is not a superclass of 'Bounded' since types that are not-- totally ordered may also have upper and lower bounds.---- The 'Bounded' class may be derived for any enumeration type;-- 'minBound' is the first constructor listed in the @data@ declaration-- and 'maxBound' is the last.-- 'Bounded' may also be derived for single-constructor datatypes whose-- constituent types are in 'Bounded'.classBoundedawhereminBound,maxBound::a-- | Class 'Enum' defines operations on sequentially ordered types.---- The @enumFrom@... methods are used in Haskell's translation of-- arithmetic sequences.---- Instances of 'Enum' may be derived for any enumeration type (types-- whose constructors have no fields).  The nullary constructors are-- assumed to be numbered left-to-right by 'fromEnum' from @0@ through @n-1@.-- See Chapter 10 of the /Haskell Report/ for more details.---- For any type that is an instance of class 'Bounded' as well as 'Enum',-- the following should hold:---- * The calls @'succ' 'maxBound'@ and @'pred' 'minBound'@ should result in--   a runtime error.---- * 'fromEnum' and 'toEnum' should give a runtime error if the--   result value is not representable in the result type.--   For example, @'toEnum' 7 :: 'Bool'@ is an error.---- * 'enumFrom' and 'enumFromThen' should be defined with an implicit bound,--   thus:---- >    enumFrom     x   = enumFromTo     x maxBound-- >    enumFromThen x y = enumFromThenTo x y bound-- >      where-- >        bound | fromEnum y >= fromEnum x = maxBound-- >              | otherwise                = minBound--classEnumawhere-- | the successor of a value.  For numeric types, 'succ' adds 1.succ::a->a-- | the predecessor of a value.  For numeric types, 'pred' subtracts 1.pred::a->a-- | Convert from an 'Int'.toEnum::Int->a-- | Convert to an 'Int'.-- It is implementation-dependent what 'fromEnum' returns when-- applied to a value that is too large to fit in an 'Int'.fromEnum::a->Int-- | Used in Haskell's translation of @[n..]@.enumFrom::a->[a]-- | Used in Haskell's translation of @[n,n'..]@.enumFromThen::a->a->[a]-- | Used in Haskell's translation of @[n..m]@.enumFromTo::a->a->[a]-- | Used in Haskell's translation of @[n,n'..m]@.enumFromThenTo::a->a->a->[a]succ=toEnum.(`plusInt`oneInt).fromEnumpred=toEnum.(`minusInt`oneInt).fromEnumenumFromx=maptoEnum[fromEnumx..]enumFromThenxy=maptoEnum[fromEnumx,fromEnumy..]enumFromToxy=maptoEnum[fromEnumx..fromEnumy]enumFromThenTox1x2y=maptoEnum[fromEnumx1,fromEnumx2..fromEnumy]-- Default methods for bounded enumerationsboundedEnumFrom::(Enuma,Boundeda)=>a->[a]boundedEnumFromn=maptoEnum[fromEnumn..fromEnum(maxBound`asTypeOf`n)]boundedEnumFromThen::(Enuma,Boundeda)=>a->a->[a]boundedEnumFromThenn1n2|i_n2>=i_n1=maptoEnum[i_n1,i_n2..fromEnum(maxBound`asTypeOf`n1)]|otherwise=maptoEnum[i_n1,i_n2..fromEnum(minBound`asTypeOf`n1)]wherei_n1=fromEnumn1i_n2=fromEnumn2
\end{code}%*********************************************************%* *\subsection{Tuples}%* *%*********************************************************\begin{code}
instanceBounded()whereminBound=()maxBound=()instanceEnum()wheresucc_=error"Prelude.Enum.().succ: bad argument"pred_=error"Prelude.Enum.().pred: bad argument"toEnumx|x==zeroInt=()|otherwise=error"Prelude.Enum.().toEnum: bad argument"fromEnum()=zeroIntenumFrom()=[()]enumFromThen()()=letmany=():manyinmanyenumFromTo()()=[()]enumFromThenTo()()()=letmany=():manyinmany
\end{code}\begin{code}
-- Report requires instances up to 15instance(Boundeda,Boundedb)=>Bounded(a,b)whereminBound=(minBound,minBound)maxBound=(maxBound,maxBound)instance(Boundeda,Boundedb,Boundedc)=>Bounded(a,b,c)whereminBound=(minBound,minBound,minBound)maxBound=(maxBound,maxBound,maxBound)instance(Boundeda,Boundedb,Boundedc,Boundedd)=>Bounded(a,b,c,d)whereminBound=(minBound,minBound,minBound,minBound)maxBound=(maxBound,maxBound,maxBound,maxBound)instance(Boundeda,Boundedb,Boundedc,Boundedd,Boundede)=>Bounded(a,b,c,d,e)whereminBound=(minBound,minBound,minBound,minBound,minBound)maxBound=(maxBound,maxBound,maxBound,maxBound,maxBound)instance(Boundeda,Boundedb,Boundedc,Boundedd,Boundede,Boundedf)=>Bounded(a,b,c,d,e,f)whereminBound=(minBound,minBound,minBound,minBound,minBound,minBound)maxBound=(maxBound,maxBound,maxBound,maxBound,maxBound,maxBound)instance(Boundeda,Boundedb,Boundedc,Boundedd,Boundede,Boundedf,Boundedg)=>Bounded(a,b,c,d,e,f,g)whereminBound=(minBound,minBound,minBound,minBound,minBound,minBound,minBound)maxBound=(maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound)instance(Boundeda,Boundedb,Boundedc,Boundedd,Boundede,Boundedf,Boundedg,Boundedh)=>Bounded(a,b,c,d,e,f,g,h)whereminBound=(minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound)maxBound=(maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound)instance(Boundeda,Boundedb,Boundedc,Boundedd,Boundede,Boundedf,Boundedg,Boundedh,Boundedi)=>Bounded(a,b,c,d,e,f,g,h,i)whereminBound=(minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound)maxBound=(maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound)instance(Boundeda,Boundedb,Boundedc,Boundedd,Boundede,Boundedf,Boundedg,Boundedh,Boundedi,Boundedj)=>Bounded(a,b,c,d,e,f,g,h,i,j)whereminBound=(minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound)maxBound=(maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound)instance(Boundeda,Boundedb,Boundedc,Boundedd,Boundede,Boundedf,Boundedg,Boundedh,Boundedi,Boundedj,Boundedk)=>Bounded(a,b,c,d,e,f,g,h,i,j,k)whereminBound=(minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound)maxBound=(maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound)instance(Boundeda,Boundedb,Boundedc,Boundedd,Boundede,Boundedf,Boundedg,Boundedh,Boundedi,Boundedj,Boundedk,Boundedl)=>Bounded(a,b,c,d,e,f,g,h,i,j,k,l)whereminBound=(minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound)maxBound=(maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound)instance(Boundeda,Boundedb,Boundedc,Boundedd,Boundede,Boundedf,Boundedg,Boundedh,Boundedi,Boundedj,Boundedk,Boundedl,Boundedm)=>Bounded(a,b,c,d,e,f,g,h,i,j,k,l,m)whereminBound=(minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound)maxBound=(maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound)instance(Boundeda,Boundedb,Boundedc,Boundedd,Boundede,Boundedf,Boundedg,Boundedh,Boundedi,Boundedj,Boundedk,Boundedl,Boundedm,Boundedn)=>Bounded(a,b,c,d,e,f,g,h,i,j,k,l,m,n)whereminBound=(minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound)maxBound=(maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound)instance(Boundeda,Boundedb,Boundedc,Boundedd,Boundede,Boundedf,Boundedg,Boundedh,Boundedi,Boundedj,Boundedk,Boundedl,Boundedm,Boundedn,Boundedo)=>Bounded(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o)whereminBound=(minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound,minBound)maxBound=(maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound,maxBound)
\end{code}%*********************************************************%* *\subsection{Type @Bool@}%* *%*********************************************************\begin{code}
instanceBoundedBoolwhereminBound=FalsemaxBound=TrueinstanceEnumBoolwheresuccFalse=TruesuccTrue=error"Prelude.Enum.Bool.succ: bad argument"predTrue=FalsepredFalse=error"Prelude.Enum.Bool.pred: bad argument"toEnumn|n==zeroInt=False|n==oneInt=True|otherwise=error"Prelude.Enum.Bool.toEnum: bad argument"fromEnumFalse=zeroIntfromEnumTrue=oneInt-- Use defaults for the restenumFrom=boundedEnumFromenumFromThen=boundedEnumFromThen
\end{code}%*********************************************************%* *\subsection{Type @Ordering@}%* *%*********************************************************\begin{code}
instanceBoundedOrderingwhereminBound=LTmaxBound=GTinstanceEnumOrderingwheresuccLT=EQsuccEQ=GTsuccGT=error"Prelude.Enum.Ordering.succ: bad argument"predGT=EQpredEQ=LTpredLT=error"Prelude.Enum.Ordering.pred: bad argument"toEnumn|n==zeroInt=LT|n==oneInt=EQ|n==twoInt=GTtoEnum_=error"Prelude.Enum.Ordering.toEnum: bad argument"fromEnumLT=zeroIntfromEnumEQ=oneIntfromEnumGT=twoInt-- Use defaults for the restenumFrom=boundedEnumFromenumFromThen=boundedEnumFromThen
\end{code}%*********************************************************%* *\subsection{Type @Char@}%* *%*********************************************************\begin{code}
instanceBoundedCharwhereminBound='\0'maxBound='\x10FFFF'instanceEnumCharwheresucc(C#c#)|not(ord#c#==#0x10FFFF#)=C#(chr#(ord#c#+#1#))|otherwise=error("Prelude.Enum.Char.succ: bad argument")pred(C#c#)|not(ord#c#==#0#)=C#(chr#(ord#c#-#1#))|otherwise=error("Prelude.Enum.Char.pred: bad argument")toEnum=chrfromEnum=ord{-# INLINE enumFrom #-}enumFrom(C#x)=eftChar(ord#x)0x10FFFF#-- Blarg: technically I guess enumFrom isn't strict!{-# INLINE enumFromTo #-}enumFromTo(C#x)(C#y)=eftChar(ord#x)(ord#y){-# INLINE enumFromThen #-}enumFromThen(C#x1)(C#x2)=efdChar(ord#x1)(ord#x2){-# INLINE enumFromThenTo #-}enumFromThenTo(C#x1)(C#x2)(C#y)=efdtChar(ord#x1)(ord#x2)(ord#y){-# RULES"eftChar"       [~1] forall x y.        eftChar x y       = build (\c n -> eftCharFB c n x y)"efdChar"       [~1] forall x1 x2.      efdChar x1 x2     = build (\ c n -> efdCharFB c n x1 x2)"efdtChar"      [~1] forall x1 x2 l.    efdtChar x1 x2 l  = build (\ c n -> efdtCharFB c n x1 x2 l)"eftCharList"   [1]  eftCharFB  (:) [] = eftChar"efdCharList"   [1]  efdCharFB  (:) [] = efdChar"efdtCharList"  [1]  efdtCharFB (:) [] = efdtChar #-}-- We can do better than for Ints because we don't-- have hassles about arithmetic overflow at maxBound{-# INLINE [0] eftCharFB #-}eftCharFB::(Char->a->a)->a->Int#->Int#->aeftCharFBcnx0y=gox0wheregox|x>#y=n|otherwise=C#(chr#x)`c`go(x+#1#)eftChar::Int#->Int#->StringeftCharxy|x>#y=[]|otherwise=C#(chr#x):eftChar(x+#1#)y-- For enumFromThenTo we give up on inlining{-# NOINLINE [0] efdCharFB #-}efdCharFB::(Char->a->a)->a->Int#->Int#->aefdCharFBcnx1x2|delta>=#0#=go_up_char_fbcnx1delta0x10FFFF#|otherwise=go_dn_char_fbcnx1delta0#where!delta=x2-#x1efdChar::Int#->Int#->StringefdCharx1x2|delta>=#0#=go_up_char_listx1delta0x10FFFF#|otherwise=go_dn_char_listx1delta0#where!delta=x2-#x1{-# NOINLINE [0] efdtCharFB #-}efdtCharFB::(Char->a->a)->a->Int#->Int#->Int#->aefdtCharFBcnx1x2lim|delta>=#0#=go_up_char_fbcnx1deltalim|otherwise=go_dn_char_fbcnx1deltalimwhere!delta=x2-#x1efdtChar::Int#->Int#->Int#->StringefdtCharx1x2lim|delta>=#0#=go_up_char_listx1deltalim|otherwise=go_dn_char_listx1deltalimwhere!delta=x2-#x1go_up_char_fb::(Char->a->a)->a->Int#->Int#->Int#->ago_up_char_fbcnx0deltalim=go_upx0wherego_upx|x>#lim=n|otherwise=C#(chr#x)`c`go_up(x+#delta)go_dn_char_fb::(Char->a->a)->a->Int#->Int#->Int#->ago_dn_char_fbcnx0deltalim=go_dnx0wherego_dnx|x<#lim=n|otherwise=C#(chr#x)`c`go_dn(x+#delta)go_up_char_list::Int#->Int#->Int#->Stringgo_up_char_listx0deltalim=go_upx0wherego_upx|x>#lim=[]|otherwise=C#(chr#x):go_up(x+#delta)go_dn_char_list::Int#->Int#->Int#->Stringgo_dn_char_listx0deltalim=go_dnx0wherego_dnx|x<#lim=[]|otherwise=C#(chr#x):go_dn(x+#delta)
\end{code}%*********************************************************%* *\subsection{Type @Int@}%* *%*********************************************************Be careful about these instances. (a) remember that you have to count down as well as up e.g. [13,12..0] (b) be careful of Int overflow (c) remember that Int is bounded, so [1..] terminates at maxIntAlso NB that the Num class isn't available in this module. \begin{code}
instanceBoundedIntwhereminBound=minIntmaxBound=maxIntinstanceEnumIntwheresuccx|x==maxBound=error"Prelude.Enum.succ{Int}: tried to take `succ' of maxBound"|otherwise=x`plusInt`oneIntpredx|x==minBound=error"Prelude.Enum.pred{Int}: tried to take `pred' of minBound"|otherwise=x`minusInt`oneInttoEnumx=xfromEnumx=x{-# INLINE enumFrom #-}enumFrom(I#x)=eftIntxmaxInt#where!(I#maxInt#)=maxInt-- Blarg: technically I guess enumFrom isn't strict!{-# INLINE enumFromTo #-}enumFromTo(I#x)(I#y)=eftIntxy{-# INLINE enumFromThen #-}enumFromThen(I#x1)(I#x2)=efdIntx1x2{-# INLINE enumFromThenTo #-}enumFromThenTo(I#x1)(I#x2)(I#y)=efdtIntx1x2y------------------------------------------------------- eftInt and eftIntFB deal with [a..b], which is the-- most common form, so we take a lot of care-- In particular, we have rules for deforestation{-# RULES"eftInt"        [~1] forall x y. eftInt x y = build (\ c n -> eftIntFB c n x y)"eftIntList"    [1] eftIntFB  (:) [] = eftInt #-}eftInt::Int#->Int#->[Int]-- [x1..x2]eftIntx0y|x0>#y=[]|otherwise=gox0wheregox=I#x:ifx==#ythen[]elsego(x+#1#){-# INLINE [0] eftIntFB #-}eftIntFB::(Int->r->r)->r->Int#->Int#->reftIntFBcnx0y|x0>#y=n|otherwise=gox0wheregox=I#x`c`ifx==#ythennelsego(x+#1#)-- Watch out for y=maxBound; hence ==, not >-- Be very careful not to have more than one "c"-- so that when eftInfFB is inlined we can inline-- whatever is bound to "c"------------------------------------------------------- efdInt and efdtInt deal with [a,b..] and [a,b..c].-- The code is more complicated because of worries about Int overflow.{-# RULES"efdtInt"       [~1] forall x1 x2 y.                     efdtInt x1 x2 y = build (\ c n -> efdtIntFB c n x1 x2 y)"efdtIntUpList" [1]  efdtIntFB (:) [] = efdtInt #-}efdInt::Int#->Int#->[Int]-- [x1,x2..maxInt]efdIntx1x2|x2>=#x1=casemaxIntofI#y->efdtIntUpx1x2y|otherwise=caseminIntofI#y->efdtIntDnx1x2yefdtInt::Int#->Int#->Int#->[Int]-- [x1,x2..y]efdtIntx1x2y|x2>=#x1=efdtIntUpx1x2y|otherwise=efdtIntDnx1x2y{-# INLINE [0] efdtIntFB #-}efdtIntFB::(Int->r->r)->r->Int#->Int#->Int#->refdtIntFBcnx1x2y|x2>=#x1=efdtIntUpFBcnx1x2y|otherwise=efdtIntDnFBcnx1x2y-- Requires x2 >= x1efdtIntUp::Int#->Int#->Int#->[Int]efdtIntUpx1x2y-- Be careful about overflow!|y<#x2=ify<#x1then[]else[I#x1]|otherwise=-- Common case: x1 <= x2 <= ylet!delta=x2-#x1-- >= 0!y'=y-#delta-- x1 <= y' <= y; hence y' is representable-- Invariant: x <= y-- Note that: z <= y' => z + delta won't overflow-- so we are guaranteed not to overflow if/when we recursego_upx|x>#y'=[I#x]|otherwise=I#x:go_up(x+#delta)inI#x1:go_upx2-- Requires x2 >= x1efdtIntUpFB::(Int->r->r)->r->Int#->Int#->Int#->refdtIntUpFBcnx1x2y-- Be careful about overflow!|y<#x2=ify<#x1thennelseI#x1`c`n|otherwise=-- Common case: x1 <= x2 <= ylet!delta=x2-#x1-- >= 0!y'=y-#delta-- x1 <= y' <= y; hence y' is representable-- Invariant: x <= y-- Note that: z <= y' => z + delta won't overflow-- so we are guaranteed not to overflow if/when we recursego_upx|x>#y'=I#x`c`n|otherwise=I#x`c`go_up(x+#delta)inI#x1`c`go_upx2-- Requires x2 <= x1efdtIntDn::Int#->Int#->Int#->[Int]efdtIntDnx1x2y-- Be careful about underflow!|y>#x2=ify>#x1then[]else[I#x1]|otherwise=-- Common case: x1 >= x2 >= ylet!delta=x2-#x1-- <= 0!y'=y-#delta-- y <= y' <= x1; hence y' is representable-- Invariant: x >= y-- Note that: z >= y' => z + delta won't underflow-- so we are guaranteed not to underflow if/when we recursego_dnx|x<#y'=[I#x]|otherwise=I#x:go_dn(x+#delta)inI#x1:go_dnx2-- Requires x2 <= x1efdtIntDnFB::(Int->r->r)->r->Int#->Int#->Int#->refdtIntDnFBcnx1x2y-- Be careful about underflow!|y>#x2=ify>#x1thennelseI#x1`c`n|otherwise=-- Common case: x1 >= x2 >= ylet!delta=x2-#x1-- <= 0!y'=y-#delta-- y <= y' <= x1; hence y' is representable-- Invariant: x >= y-- Note that: z >= y' => z + delta won't underflow-- so we are guaranteed not to underflow if/when we recursego_dnx|x<#y'=I#x`c`n|otherwise=I#x`c`go_dn(x+#delta)inI#x1`c`go_dnx2
\end{code}
[8]ページ先頭

©2009-2025 Movatter.jp