Skip to content

Add a more complete example for the special SPEC argument to the user guide

In the section for -fspec-constr in the user guide there is an example of how to use SPEC to force a loop to be unrolled by spec constr.

However, this argument doesn't do anything until foldl is called with a specific argument. It wasn't clear to me exactly how this worked as the example was incomplete. Below is a complete file which shows how the optimisation unrolls the list completely such that res2 = 6 in core.

{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE ExistentialQuantification #-}
module Foo where
import GHC.Types

data Stream a = forall s.
                Stream !(s -> Step a s)  -- a stepper function
                !s                       -- an initial state

data Step a s = Yield a !s
               | Skip    !s
               | Done

s2 = Stream s [1,2,3]

s [] = Done
s (x:xs) = Yield x xs

res2 = Foo.foldl (+) 0 s2


foldl :: (a -> b -> a) -> a -> Stream b -> a
{-# INLINE foldl #-}
foldl f z (Stream step s) = foldl_loop SPEC z s
    where
      foldl_loop !sPEC z s = case step s of
                              Yield x s' -> foldl_loop sPEC (f z x) s'
                              Skip  s'     -> foldl_loop sPEC z s'
                              Done -> z
Trac metadata
Trac field Value
Version 8.0.1
Type Task
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information