Strict
pragma certainly let GHC evaluate everything strictly, but into only Weak Head Normal Form. For example:
(a, b) = (error "a", error "b")
If above code exists under Strict
pragma, any error arises. Let's see your code:
test_fibs n =
let fibs = 0 : 1 : my_zipWith (+) fibs (tail fibs) in
take n fibs
fibs
called recursively but in list cons, so now whole list is WHNF. That is reason why your code didn't stack.
This post will help you also. Enjoy recursion and laziness!
Add:
An easy way, to use deepseq:
{-# LANGUAGE Strict #-}
import Control.DeepSeq
my_zipWith f x [] = []
my_zipWith f [] y = []
my_zipWith f (x:xt) (y:yt) = force $ f x y : my_zipWith f xt yt
test_fibs :: Int -> [Int]
test_fibs n =
let fibs = 0 : 1 : my_zipWith (+) fibs (tail fibs) in
force $ take n fibs
main = do
putStr $ show $ test_fibs 15
force
defined as force x = x `deepSeq` x
, deepSeq
evaluate an expression deeply literally to NF (Normal Form). This conversion is achieved with GHC.Generics
. If convert manually, just have to evaluate inside of data, so can rewrite following:
{-# LANGUAGE Strict #-}
my_zipWith f x [] = []
my_zipWith f [] y = []
my_zipWith f (x:xt) (y:yt) = f x y : go
where
go = my_zipWith f xt yt
test_fibs n =
let
fib2 = my_zipWith (+) fibs (tail fibs)
fibs = 0 : 1 : fib2
in
take n fibs
main = do
putStr $ show $ test_fibs 15
But they can't stack actually. Because GHC can detect infinite loop, but it's another story.