And because I just find this really fascinating, here's a more direct implementation of `fact`
data Stream a = Stream a (Stream a)
deriving Functor
tabulate :: (Int -> a) -> Stream a
tabulate f = go 0 where
go n = Stream (f n) (go (succ n))
index :: Stream a -> (Int -> a)
index (Stream a _) 0 = a
index (Stream a st) n = index st (pred n)
-- btw: tabulate . index == id
-- and index . tabulate == id
fact :: Int -> Int
fact n = index (loeb facts) n where
facts :: Stream (Stream Int -> Int)
facts = tabulate $ \i stream -> i * index stream (i-1)
Then `loeb` completes the computation using spreadsheet recursion.