Update comment about non-fusing foldl
[list-fusion-probe.git] / Data / List / Fusion / Probe.hs
1 {-# LANGUAGE CPP #-}
2 {- |
3    Copyright  : Copyright (C) 2014 Joachim Breitner
4    License    : BSD3
5
6    Maintainer : Joachim Breitner <mail@joachim-breitner.de>
7    Stability  : stable
8    Portability: GHCspecific
9 -}
10
11 module Data.List.Fusion.Probe where
12
13
14 import GHC.Exts (build, augment)
15
16 #if MIN_VERSION_base(4,8,0)
17 import Prelude hiding (foldr)
18 import GHC.OldList (foldr)
19 #endif
20
21 -- | This function can be wrapped around a list that should be compiled away by
22 -- list fusion. If it does, this function will disappear. If not, it will throw
23 -- an error at runtime.
24 --
25 -- > main = print $ foldl (+) 0 (fuseThis [0..1000])
26 --
27 -- Will print @Test: fuseList: List did not fuse@, while
28 --
29 -- > main = print $ foldr (+) 0 (fuseThis [0..1000])
30 --
31 -- will print @500500@.
32 --
33 -- (These examples are from the time before GHC-7.10. Since then, 'foldl' fuses as well.)
34
35 fuseThis :: [a] -> [a]
36 fuseThis = id
37
38 {-# NOINLINE fuseThis #-}
39
40 {-# RULES
41 "fold/fuseThis/build" [~0]
42     forall k z (g::forall b. (a->b->b) -> b -> b) .
43     foldr k z (fuseThis (build g)) = g k z
44
45 "foldr/fuseThis/augment" [~0]
46     forall k z xs (g::forall b. (a->b->b) -> b -> b) .
47     foldr k z (fuseThis (augment g xs)) = g k (foldr k z xs)
48  #-}
49
50 {-# RULES
51 "fuseThis/fail" [0]
52     fuseThis = error "fuseThis: List did not fuse"
53  #-}
54