Dear bug chasers,
ghc-2.02 is unhappy with the following program (it essentially contains
a wonderful class definition for sets and a simple instance, ordered
list without duplicates):
===============================================================================
> module Set ( module Set )
> where
> import Prelude hiding ( filter )
> import qualified Prelude -- !!!!GHC bug
> import List ( genericLength, sort )
> data SeqView t a = Null
> | Cons a (t a)
> class Set set where
> empty :: (Ord a) => set a
> single :: (Ord a) => a -> set a --
>singleton
> add :: (Ord a) => a -> set a -> set a -- insert
> addWith :: (Ord a) => (a -> a -> a) -> a -> set a -> set a
> union :: (Ord a) => set a -> set a -> set a
> unionWith :: (Ord a) => (a -> a -> a) -> set a -> set a -> set a
> delete :: (Ord a) => a -> set a -> set a
> intersect :: (Ord a) => set a -> set a -> set a
> minus :: (Ord a) => set a -> set a -> set a
> partition :: (Ord a) => (a -> Bool) -> set a -> (set a, set a)
> filter :: (Ord a) => (a -> Bool) -> set a -> set a
> unionMap :: (Ord a, Ord b) => set a -> (a -> set b) -> set b
> isEmpty :: (Ord a) => set a -> Bool
> isSingle :: (Ord a) => set a -> Bool -- isSingleton
> intersecting :: (Ord a) => set a -> set a -> Bool
> isSubsetOf :: (Ord a) => set a -> set a -> Bool
> member :: (Ord a) => a -> set a -> Bool -- elem
> fold :: (Ord a) => (a -> b -> b) -> b -> set a -> b
> fold1 :: (Ord a) => (a -> a -> a) -> set a -> a
> split :: (Ord a) => set a -> SeqView set a
> splitMin :: (Ord a) => set a -> SeqView set a
> splitMax :: (Ord a) => set a -> SeqView set a
> within :: (Ord a) => (a, a) -> set a -> [a] -- range
> size :: (Ord a) => set a -> Int
> genericSize :: (Ord a, Integral n) => set a -> n
> fromList :: (Ord a) => [a] -> set a
> toList :: (Ord a) => set a -> [a]
> fromOrderedList :: (Ord a) => [a] -> set a
> toOrderedList :: (Ord a) => set a -> [a]
> single a = add a empty
> add = addWith (\a b -> b)
> addWith f a s = unionWith f (single a) s
> union = unionWith (\a b -> b)
> unionWith f s1 s2 = fold (addWith f) s1 s2
> delete a s = filter (/= a) s
> intersect s1 s2 = filter (\a -> member a s2) s1
> minus s1 s2 = filter (\a -> not (member a s2)) s1
> partition p s = (filter p s, filter (not . p) s)
> filter p s = fold condAdd empty s
> where condAdd a s
> | p a = add a s
> | otherwise = s
> unionMap s f = fold (union . f) empty s
> isEmpty s = size s == 0
> isSingle s = size s == 1
> intersecting s1 s2 = not (isEmpty (s1 `intersect` s2))
> isSubsetOf s1 s2 = isEmpty (s1 `minus` s2)
> member a = fold (\b r -> a ==b || r) False
> fold (*) e s = case split s of
> Null -> e
> Cons a s -> a * fold (*) e s
> fold1 (*) s = case split s of
> Null -> error "fold1 of empty set"
> Cons a s -> fold (*) a s
> within (l, r) = fold condCons []
> where condCons a x
> | l <= a && a <= r = a : x
> | otherwise = x
> size = fold (\_ n -> n + 1) 0
> genericSize = fold (\_ n -> n + 1) 0
> fromList = foldr add empty
> toList = fold (:) []
> fromOrderedList = fromList -- Sortierung wird nicht
>ausgenutzt
> toOrderedList s = case splitMin s of
> Null -> []
> Cons a s -> a : toOrderedList s
> addMany :: (Set set, Ord a) => [a] -> set a -> set a
> -- addMany x s = foldr add s x -- insertion sort
> addMany x s = fromList x `union` s -- merge sort
> unionMany :: (Set set, Ord a) => [set a] -> set a
> unionMany = foldm union empty
> deleteMany :: (Set set, Ord a) => [a] -> set a -> set a
> -- deleteMany x s = foldr delete s x
> deleteMany x s = s `minus` fromList x
> intersectMany :: (Set set, Ord a) => [set a] -> set a
> intersectMany = foldm intersect empty
> class (Set set) => SubSet set where
> emptyOf :: (Ord a) => (a, a) -> set a
> complement :: (Ord a) => set a -> set a
> instance Set [] where
Construction.
> empty = []
> single a = [a]
> addWith f a [] = [a]
> addWith f a x@(b:x') = case compare a b of
> LT -> a : x
> EQ -> f b a : x'
> GT -> b : addWith f a x'
> unionWith f [] y = y
> unionWith f x@(_:_) [] = x
> unionWith f x@(a:x') y@(b:y') = case compare a b of
> LT -> a : unionWith f x' y
> EQ -> f a b : unionWith f x' y'
> GT -> b : unionWith f x y'
Modification.
> delete a [] = []
> delete a x@(b:x') = case compare a b of
> LT -> x
> EQ -> x'
> GT -> b : delete a x'
> intersect [] y = []
> intersect x@(_:_) [] = []
> intersect x@(a:x') y@(b:y') = case compare a b of
> LT -> intersect x' y
> EQ -> a : intersect x' y'
> GT -> intersect x y'
> minus [] y = []
> minus x@(_:_) [] = x
> minus x@(a:x') y@(b:y') = case compare a b of
> LT -> a : minus x' y
> EQ -> minus x' y'
> GT -> minus x y'
> filter = Prelude.filter
> unionMap s f = foldm union empty (map f s)
Testing.
> isEmpty = null
> isSingle [_] = True
> isSingle _ = False
> intersecting [] y = False
> intersecting x@(_:_) [] = False
> intersecting x@(a:x') y@(b:y') = case compare a b of
> LT -> intersecting x' y
> EQ -> True
> GT -> intersecting x y'
> isSubsetOf [] y = True
> isSubsetOf x@(_:_) [] = False
> isSubsetOf x@(a:x') y@(b:y') = case compare a b of
> LT -> False
> EQ -> isSubsetOf x' y'
> GT -> isSubsetOf x y'
> member a [] = False
> member a x@(b:x') = case compare a b of
> LT -> False
> EQ -> True
> GT -> member a x'
Extraction.
> fold = foldr
> fold1 = foldr1
> split [] = Null
> split (a:x) = Cons a x
> splitMin [] = Null
> splitMin (a:x) = Cons a x
> splitMax [] = Null
> splitMax x = Cons (last x) (init x)
> within (l, r) = takeWhile (<= r) . dropWhile (< l)
Size.
> size = length
> size = genericLength
Conversion.
> fromList = unique . sort
> toList = id
> fromOrderedList = unique
> toOrderedList = id
> foldm :: (a -> a -> a) -> a -> [a] -> a
> foldm (*) e [] = e
> foldm (*) e x = fst (f (length x) x)
> where f n x = if n==1 then (head x, tail x)
> else let m = n `div` 2
> (a, y) = f m x
> (b, z) = f (n - m) y
> in (a * b, z)
> unique :: (Eq a) => [a] -> [a]
> unique [] = []
> unique [a] = [a]
> unique (a:x@(b:_)) = if a==b then unique x else a : unique x
===============================================================================
And here is what happens:
===============================================================================
> ghc-2.02 -v -c Set.lhs
The Glorious Glasgow Haskell Compilation System, version 2.02, patchlevel 0
literate pre-processor:
echo '#line 1 "Set.lhs"' > /tmp/ghc3903.lpp &&
/home/III/a/ralf/FP/fptools/lib/sparc-sun-solaris2/ghc-2.02/unlit Set.lhs - >>
/tmp/ghc3903.lpp
real 0.0
user 0.0
sys 0.0
Ineffective C pre-processor:
echo '#line 1 "Set.lhs"' > /tmp/ghc3903.cpp && cat /tmp/ghc3903.lpp >>
/tmp/ghc3903.cpp
real 0.0
user 0.0
sys 0.0
Haskell compiler:
/home/III/a/ralf/FP/fptools/lib/sparc-sun-solaris2/ghc-2.02/hsc ,-W
,/tmp/ghc3903.cpp -hisuf-prelude=.hi -hisuf=.hi -fignore-interface-pragmas
-fomit-interface-pragmas -fsimplify \( -ffloat-lets-exposing-whnf -ffloat-primops-ok
-fcase-of-case -freuse-con -fpedantic-bottoms -fsimpl-uf-use-threshold0
-fessential-unfoldings-only -fmax-simplifier-iterations4 \)
-himap=.:/home/III/a/ralf/FP/fptools/lib/sparc-sun-solaris2/ghc-2.02/imports -v
-hifile=/tmp/ghc3903.hi -S=/tmp/ghc3903.s +RTS -H6000000 -K1000000
Glasgow Haskell Compiler, version 2.02, for Haskell 1.3
panic! (the `impossible' happened):
lookupBindC:no info!
for: ds_d2ZA
(probably: data dependencies broken by an optimisation pass)
static binds for:
Set.scsel_SubSetSetSet{-a1Hh,x-}
m.map_a1Hi
m.==_a1Hj
m.fromInt_a1Hk
lit_a1Hl
lit_a1Hn
m.+_a1Ho
ds_d2Zd
ds_d2Ze
ds_d2Zf
ds_d2Zg
ds_d2Zh
ds_d2Zi
ds_d2Zj
ds_d2Zk
ds_d2Zl
ds_d2Zm
ds_d2Zn
ds_d2Zo
ds_d2Zp
ds_d2Zq
ds_d2Zr
ds_d2Zs
ds_d2Zt
ds_d2Zu
ds_d2Zv
ds_d2Zw
ds_d2Zx
ds_d2Zy
ds_d2Zz
ds_d2ZB
ds_d2ZC
ds_d2ZD
ds_d2ZE
ds_d2ZF
ds_d42a
ds_d44f
Set.foldm{-r80,x-}
Set.unique{-r81,x-}
Set.Null{-reF,x-}
Set.Cons{-reG,x-}
Set.empty{-reH,x-}
Set.single{-reI,x-}
Set.add{-reJ,x-}
Set.addWith{-reK,x-}
Set.union{-reL,x-}
Set.unionWith{-reM,x-}
Set.delete{-reN,x-}
Set.intersect{-reO,x-}
Set.minus{-reP,x-}
Set.partition{-reQ,x-}
Set.filter{-reR,x-}
Set.unionMap{-reS,x-}
Set.isEmpty{-reT,x-}
Set.isSingle{-reU,x-}
Set.intersecting{-reV,x-}
Set.isSubsetOf{-reW,x-}
Set.member{-reX,x-}
Set.fold{-reY,x-}
Set.fold1{-reZ,x-}
Set.split{-rf0,x-}
Set.splitMin{-rf1,x-}
Set.splitMax{-rf2,x-}
Set.within{-rf3,x-}
Set.size{-rf4,x-}
Set.genericSize{-rf5,x-}
Set.fromList{-rf6,x-}
Set.toList{-rf7,x-}
Set.fromOrderedList{-rf8,x-}
Set.toOrderedList{-rf9,x-}
Set.emptyOf{-rfa,x-}
Set.complement{-rfb,x-}
Set.$mempty{-r1o5,x-}
Set.$msingle{-r1o6,x-}
Set.$madd{-r1o7,x-}
Set.$maddWith{-r1o8,x-}
Set.$munion{-r1o9,x-}
Set.$munionWith{-r1oa,x-}
Set.$mdelete{-r1ob,x-}
Set.$mintersect{-r1oc,x-}
Set.$mminus{-r1od,x-}
Set.$mpartition{-r1oe,x-}
Set.$mfilter{-r1of,x-}
Set.$munionMap{-r1og,x-}
Set.$misEmpty{-r1oh,x-}
Set.$misSingle{-r1oi,x-}
Set.$mintersecting{-r1oj,x-}
Set.$misSubsetOf{-r1ok,x-}
Set.$mmember{-r1ol,x-}
Set.$mfold{-r1om,x-}
Set.$mfold1{-r1on,x-}
Set.$msplit{-r1oo,x-}
Set.$msplitMin{-r1op,x-}
Set.$msplitMax{-r1oq,x-}
Set.$mwithin{-r1or,x-}
Set.$msize{-r1os,x-}
Set.$mgenericSize{-r1ot,x-}
Set.$mfromList{-r1ou,x-}
Set.$mtoList{-r1ov,x-}
Set.$mfromOrderedList{-r1ow,x-}
Set.$mtoOrderedList{-r1ox,x-}
Set.$memptyOf{-r1Hf,x-}
Set.$mcomplement{-r1Hg,x-}
Set.$d2{-r2Sq,x-}
Set.$d1{-r2U9,x-}
nrlit_sbmP
nrlit_sbmQ
nrlit_sbmR
nrlit_sbmS
nrlit_sbmT
nrlit_sbmU
nrlit_sbmV
local binds for:
Please report it as a compiler bug to [EMAIL PROTECTED]
real 5.7
user 4.9
sys 0.2
deleting... /tmp/ghc3903.hi /tmp/ghc3903.s
rm -f /tmp/ghc3903*
> uname -a
SunOS blei 5.5.1 Generic sun4u sparc SUNW,Ultra-1
===============================================================================
A workaround is greatly appreciated, since this file contains some very
basic stuff ...
Cheers, Ralf