You are correct.  Moand.Cont yield even runs without -O optimizing,
just slower
...
Anyone have an idea why ghci can't garbage collect it?
Is this an actual bug or an innate quirk of the REPL ?

GHCi does not "compile" with optimizations, without -O the strictness analyzer
isn't run.

The optimizer is irrelevant to whether it runs in constant space, as ghc without '-O' runs it just fine. The optimizer is only useful for speed, which is not the issue.


The difference is most likely due to strictness analysis. A well
placed strictness annotation or two should be able to make it work in GHCi as
well.

In this code, adding a strictness $! did not work.

A similar situation occurs with sum: in GHCi for large inputs it
overflows the stack, but when compiled with -O it works correctly, this is
because sum is defined with foldl and not foldl' in GHC.

As for adding one strictness annotation, the brute for approach to adding '$!' did not work:


yield :: a -> Cont [a] ()
-- original
--yield x = Cont (\c -> x : c () )
-- original in prefix form
--yield x = Cont (\c -> (((:) x) (c ())))    -- memory exhaustion
-- non-trivial
--yield x = Cont (\c -> (((:) x) $! (c ()))) -- stack overflow
-- silly
--yield x = Cont (\c -> (((:) $! x) (c ()))) -- memory exhaustion
-- definitely silly
--yield x = Cont (\c -> (((:) x) (c $! ()))) -- memory exhaustion

So adding two '$!' to the above looks like a non-starter. The asGenerator definition is

asGenerator :: Cont [a] v -> [a]
asGenerator (Cont f) = f (const [])

which has no useful place to insert a '$!'. So to use continuations in GHCI, it may be necessary to build a new version of Cont and its internals, or maybe use the callCC interface? And I had not luck adding '$!' to callCC/Cont or callCC/mapCC versions:

-- yield using callCC
yieldCC x = callCC genContCCArg
where
genContCCArg = (\oldGenContFunc ->
let
newCont = Cont { runCont = newRunCont }
newRunCont = (\contFunc -> (x:(oldRunCont contFunc)))
oldRunCont = runCont oldCont
oldCont = oldGenContFunc ()
in newCont
)


-- Use the mysterious mapCont function
yieldM x = callCC genContCCArg
where
genContCCArg = (\genContFunc -> mapCont (\xs -> x:xs) (genContFunc ()))


I found no useful explanation of mapCont via Google. It was another case of deriving the function's action from the type.

Since this is now a "gchi problem", should this be taken to the ghc mailing list as well? instead?

--
Chris

_______________________________________________
Haskell mailing list
Haskell@haskell.org
http://www.haskell.org/mailman/listinfo/haskell

Reply via email to