
Hi everyone, I've been having some trouble getting SpecConstr to work as I want it to. The following example (see end of email) came up in some code I was playing around with. The loops g1 and g2 both compute the same thing: the maximum element of the "list" (which has been fused away) of numbers from 1 to 10. Since 'maximum' is a foldl1 not a foldl, I use a strict Maybe type as an accumulator. The Maybe gets filled after the first element is seen, so the Maybe is a Just for almost the entire running of the loop. It would be good to have this recognised by SpecConstr, to create an optimised loop for the Just case. This does indeed happen for g1, but not for g2. My difficulty is that I am only able to produce code similar to g2, i.e. where the pattern matching is in a separate function, 'expose', because the 'expose' function is implemented in a type-class, like in stream-fusion. Is there some way to keep the SpecConstr while leaving the 'expose' as a separate function? Here is the code:
{-# LANGUAGE BangPatterns #-}
module Test(ans1,ans2) where
import Prelude hiding(Maybe(..))
data Maybe a = Just !a | Nothing
Nothing `mapp` Just b = Just b Just a `mapp` Just b = Just (max a b)
ans1 = g1 Nothing (0::Int)
g1 m !n = case m of Nothing -> if n > 10 then m else g1 (m `mapp` Just n) (n+1) Just x -> if n > 10 then m else g1 (m `mapp` Just n) (n+1)
ans2 = g2 Nothing (0::Int)
g2 m !n = expose m (if n > 10 then m else g2 (m `mapp` Just n) (n+1)) expose Nothing b = b expose (Just a) b = a `seq` b
On a similar note, when I was having difficulties with this problem, I started to wonder if it would be possible to come up with a more direct way to tell GHC, "do SpecConstr on this variable". From reading the source code of the stream-fusion package, it seems that the current way of doing this is with 'expose' functions like I wrote below. Could we instead have a {-# SPECCONSTR #-} pragma, to be used on function arguments, like: foo {-# SPECCONSTR #-} x y {-# SPECCONSTR #-} z = ... This pragma should say to the GHC something like "ignore conditions H2, H5 and H6 of the SpecConstr paper, for this function and this argument". Cheers, Reiner