summaryrefslogtreecommitdiff
path: root/testsuite/tests/simplCore/should_run/simplrun009.hs
diff options
context:
space:
mode:
Diffstat (limited to 'testsuite/tests/simplCore/should_run/simplrun009.hs')
-rw-r--r--testsuite/tests/simplCore/should_run/simplrun009.hs149
1 files changed, 149 insertions, 0 deletions
diff --git a/testsuite/tests/simplCore/should_run/simplrun009.hs b/testsuite/tests/simplCore/should_run/simplrun009.hs
new file mode 100644
index 0000000000..826cdeef77
--- /dev/null
+++ b/testsuite/tests/simplCore/should_run/simplrun009.hs
@@ -0,0 +1,149 @@
+{-# LANGUAGE ExistentialQuantification #-}
+
+-- This test is really meant for human looking; do a -ddump-simpl.
+
+-- The definition that you want to look at is for foo.
+-- It produces a nested unfold that should look something
+-- like the code below. Note the 'lvl1_shW'. It is BAD
+-- if this is a lambda instead; you get a lot more allocation
+-- See Note [Escaping a value lambda] in SetLevels
+
+
+{-
+ $wunfold_shU =
+ \ (ww_she :: [[a_abm]]) (ww1_shf :: Data.Maybe.Maybe (Stream.Stream a_abm)) ->
+ case ww1_shf of wild2_afo {
+ Data.Maybe.Nothing ->
+ case ww_she of wild_ad6 {
+ [] -> GHC.Base.[] @ a_abm;
+ : x_ado xs1_adp ->
+ $wunfold_shU
+ xs1_adp
+ (Data.Maybe.Just
+ @ (Stream.Stream a_abm) (Stream.Stream @ a_abm @ [a_abm]
+ *** lvl1_shW ***
+ x_ado))
+ };
+ Data.Maybe.Just ds3_afJ ->
+ case ds3_afJ of wild3_afL { Stream.Stream @ s1_afN stepb_afO sb_afP ->
+ case stepb_afO sb_afP of wild4_afR {
+ Stream.Done -> $wunfold_shU ww_she (Data.Maybe.Nothing @ (Stream.Stream a_abm));
+ Stream.Yield x_afV sb'_afW ->
+ GHC.Base.:
+ @ a_abm
+ x_afV
+ ($wunfold_shU
+ ww_she
+ (Data.Maybe.Just
+ @ (Stream.Stream a_abm) (Stream.Stream @ a_abm @ s1_afN stepb_afO sb'_afW)));
+ Stream.Skip sb'_afZ ->
+ $wunfold_shU
+ ww_she
+ (Data.Maybe.Just
+ @ (Stream.Stream a_abm) (Stream.Stream @ a_abm @ s1_afN stepb_afO sb'_afZ))
+ }
+ }
+-}
+
+
+
+module Main( main, foo ) where
+-- Must export foo to make the issue show up
+
+import Prelude hiding ( concatMap, map)
+
+main = print (sum (foo [[1,2], [3,4,5]]))
+
+foo :: Num a => [[a]] -> [a]
+foo xss = Main.concatMap (\xs -> Main.map (+1) xs) xss
+
+
+instance StreamableSequence [] where
+ stream = listToStream
+ unstream = streamToList
+ -- These inline pragmas are useless (see #5084)
+{-
+ {-# INLINE stream #-}
+ {-# INLINE unstream #-}
+-}
+
+listToStream :: [a] -> Stream a
+listToStream xs = Stream next xs
+ where next [] = Done
+ next (x:xs) = Yield x xs
+{-# INLINE [0] listToStream #-}
+
+streamToList :: Stream a -> [a]
+streamToList (Stream next s) = unfold s
+ where unfold s =
+ case next s of
+ Done -> []
+ Skip s' -> unfold s'
+ Yield x s' -> x : unfold s'
+{-# INLINE [0] streamToList #-}
+
+{-# RULES
+"stream/unstream"
+ forall s. listToStream (streamToList s) = s
+ #-}
+
+map :: (a -> b) -> [a] -> [b]
+map f = unstream . mapS f . stream
+{-# INLINE map #-}
+
+concatMap :: (a -> [b]) -> [a] -> [b]
+concatMap f = unstream . concatMapS (stream . f) . stream
+{-# INLINE concatMap #-}
+
+
+data Stream a = forall s. Stream (s -> Step a s) s
+
+data Step a s = Done
+ | Yield a s
+ | Skip s
+
+class StreamableSequence seq where
+ stream :: seq a -> Stream a
+ unstream :: Stream a -> seq a
+
+ -- axiom: stream . unstream = id
+ -- These inline pragmas are useless (see #5084)
+{-
+ {-# INLINE stream #-}
+ {-# INLINE unstream #-}
+-}
+
+{-
+--version that does not require the sequence type
+--to be polymorphic in its elements:
+
+class StreamableSequence seq a | seq -> a where
+ stream :: seq -> Stream a
+ unstream :: Stream a -> seq
+-}
+
+
+mapS :: (a -> b) -> Stream a -> Stream b
+mapS f (Stream next s0) = Stream next' s0
+ where next' s = case next s of
+ Done -> Done
+ Skip s' -> Skip s'
+ Yield x s' -> Yield (f x) s'
+{-# INLINE [0] mapS #-}
+
+
+concatMapS :: (a -> Stream b) -> Stream a -> Stream b
+concatMapS f (Stream step s) = Stream step' (s, Nothing)
+ where step' (s, Nothing) =
+ case step s of
+ Yield x s' -> Skip (s', Just (f x))
+ Skip s' -> Skip (s', Nothing)
+ Done -> Done
+
+ step' (s, Just (Stream stepb sb)) =
+ case stepb sb of
+ Yield x sb' -> Yield x (s, Just (Stream stepb sb'))
+ Skip sb' -> Skip (s, Just (Stream stepb sb'))
+ Done -> Skip (s, Nothing)
+{-# INLINE [0] concatMapS #-}
+