On Sat, Mar 03, 2007 at 08:23:08AM -0500, Isaac Dupree wrote: > Unfortunately it would be difficult for the compiler to know that no-one > is going to make an instance that does depend on its argument (as long > as it does not do full-program analysis to determine the layout of data > structures). Maybe there should be some sort of annotation on class > method arguments that are supposed to be ignored, even if only a pragma, > if it would help compilers figure this out.
indeed, I have given this some thought too, but not just for whether a type will be unused. my current thinking is something like > class Bits a where > shift :: a -> !Int -> a > > class Eq a where > (==) :: a -> a -> !Bool > > class Typeable a where > getType :: ~a -> TypeRep where '!Int' means that the class is strict in the Int argument. and ~ means it is unused. note, these are not just hints, but actually affect the class translation. shift as above would translate to something ilke > shift :: BitsDict a -> Int -> a > shift bd x i = i `seq` shiftInstance bd x i where shiftInstance selects the appropriate value from the dictionary of course, the real benefit is now that we can do unboxing on class methods! we can treat the above class declaration as if it were class Bits a where shift :: a -> Int# -> a safely and rewrite instance declarations appropriately likewise, the ! on the return value in Eq means that we should unbox it. (this is actually always safe, so perhaps a pragma will do for this, "UNPACK" seems appropriate) for the other case > class Typeable a where > getType :: ~a -> TypeRep would create a method like so > getType :: TypeableDict a -> a -> TypeRep > getType td a = getTypeInstance td (undefined `asTypeOf` a) which causes getType to always throw away its argument, allowing the compiler to make assumptions based on it. another implicit optimization that is going on in my translations above is eta-expansion of the class methods (which is independent of the optimizations given above). this is potentially unsafe, but I have been performing the optimization in jhc without ill effect and with noticable benefit. however, you can specify the "NOETA" pragma in order to suppress this auto-eta-expansion as it does decrease sharing. another option for controlling eta expansion would be something like class Eq a where (==) :: a -> !(a -> Bool) which makes explicit that the partial result of (==) applied to one argument could usefully be shared. currently, these optimization are availabe in jhc, but only via pragmas and some built in heuristics/special knowledge in the compiler. Implementing the above syntax has been on my todo list. Anecdotal examination of core leads me to believe they could be signifigantly beneficial. John -- John Meacham - ⑆repetae.net⑆john⑈ _______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell