Juanma Barranquero lektu at
Fri Oct 17 04:01:32 EDT 2003

I'm playing with rules, and I wonder if it is posible to define a rule
that will trigger for a specialization of a function.

(In the following examples, the functions are not necesarily useful or
good-style... :)

I have:

  count :: (Integral b) => (a -> Bool) -> [a] -> b
  count = count' 0
      where count' n _ [] = n
            count' n f (x:xs) | f x       = count' (n+1) f xs
                              | otherwise = count' n     f xs

with b of class Integral and not an Int because it could posibly be used
to count lists with more than maxInt elements (let's say, bytes in a
huge file, or records in a long-lived socket connection, or whatever).

Ok, if I'm not mistaken I can add:

  {-# SPECIALIZE count :: (a -> Bool) -> [a] -> Int #-}

and have the compiler add an alternate version of count for uses such

  let c :: Int = count even [1..100]

Now, to learn about RULES, I defined:

  {-# RULES
  "count/generic" forall f g xs. count f (filter g xs) = genericLength (filter (\x -> g x && f x) xs)

where I'm forced to use genericLength so the types of the LHS and RHS
can match.

Then I wondered: as I have an specialization of count which returns Int,
wouldn't be possible to do:

  {-# RULES
  "count/int" forall f g xs. count f (filter g xs) = length (filter (\x -> g x && f x) xs)

Well, the fact is that:

  testc1 n = count even (filter (\x -> x `mod` 3 > 0) [1..n])

fires "count/generic" all right, but

  testc2 :: Int -> Int
  testc2 n = count even (filter (\x -> x `mod` 3 > 0) [1..n])

does not fire "count/int".

I suppose I'm being bitten by User's Guide 7.8.2:

  "If more than one rule matches a call, GHC will choose one arbitrarily
to apply."

even if a bit later it says:

  "So a rule only matches if the types match too."

Am I understanding right and it's that so?



More information about the Glasgow-haskell-users mailing list