Я думал, что монада Cont
просто эквивалентна преобразованию CPS, поэтому, если у меня есть монадическая сумма, если я запускаю монаду Identity
, она потерпит неудачу из-за переполнения стека, и если я запусту ее вCont
Монада, все будет хорошо благодаря хвостовой рекурсии.
Итак, я написал простую программу для проверки моей идеи.Но, к моему удивлению, результат неоправдан из-за моих ограниченных знаний.
Все программы скомпилированы с использованием ghc --make Test.hs -o test && ./test
sum0 n = if n==0 then 0 else n + sum0 (n-1)
sum1 n = if n==0 then return 0 else sum1 (n-1) >>= \ v -> seq v (return (n+v))
sum2 n k = if n == 0 then k 0 else sum2 n (\v -> k (n + v))
sum3 n k = if n == 0 then k 0 else sum3 n (\ !v -> k (n + v))
sum4 n k = if n == 0 then k 0 else sum4 n (\ v -> seq v ( k (n + v)))
sum5 n = if n==0 then return 0 else sum5 (n-1) >>= \ v -> (return (n+v))
main = print (sum0 3000000)
Переполнение стека.Это разумно.
main = print (flip runCont id (sum1 3000000))
Используется память 180M, что разумно, но я не понимаю, зачем здесь нужен seq
, поскольку его продолжение не применяется до тех пор, пока n
не перейдет к0.
main = print (flip runCont id (sum5 3000000))
Переполнение стека.Зачем?
main = print (flip runCont (const 0) (sum1 3000000))
Использует 130М памяти.Это разумно.
main = print (flip runCont (const 0) (sum5 3000000))
Использует 118M памяти.Это разумно.
main = print (sum2 3000000 (const 0))
Используется много памяти (более 1 ГБ).Я думал, что sum2
эквивалентно sum5
(когда sum5
находится в Cont
монаде).Почему?
main = print (sum3 3000000 (const 0))
Использует много памяти.Я думал, что sum3
эквивалентно sum1
(Cont
монада).Зачем?
main = print (runIdentity (sum1 3000000))
Переполнение стека, именно то, что я хочу.
main = print (sum3 3000000 id)
Использует много памяти.Эквивалент sum1
, почему?
main = print (sum4 3000000 id)
Использует много памяти.Почему эквивалентно sum1?
main = print (sum [1 .. 3000000])
Переполнение стека.Источник sum = foldl (+) 0
, так что это разумно.
main = print (foldl' (+) 0 [1 .. 3000000])
Использует 1,5M.