LINUX.ORG.RU

Знатокам haskell


0

0

Вопрос знающим сей замечательный язык. Почему следующий код съедает всю память что находит и вешается? Я так понимаю, все дело в лени, но я не могу понять как ее тут побороть (в коде видны некоторые попытки в виде seq).

module Main where

import Control.Monad
import Control.Monad.ST
import Data.STRef

list = [0..10000]

res = runST $ do
        r <- newSTRef (0 :: Int)
        forM_ list $ \i -> do
          forM_ list $ \j -> do
            v <- readSTRef r
            let v' = v `seq` v + 1
            writeSTRef r v'
        readSTRef r

main = do
  putStr "Result: "
  print res


я вот так переписал - разницы никакой только лишние сущности убрал. 

res = runST $ do
        r <- newSTRef (0 :: Int)
        replicateM_ (10000^2) $ modifySTRef r succ
        readSTRef r

Так же вылетает. 
Попробовал при 1000000 и 10000000 - зависимость о времени и памяти линейная. 
95% времени тратится на GC. 
А вот почему - это надо подумать.
Ленивость тут не при чем - а вот то что инты постоянно на heap'е выделяются - это да. 
Причем никак он это соптимизировать не может сам.

imp ★★
()
Ответ на: комментарий от imp

Спасибо!
Получилось побороть с помощью unboxed STRef'ов из либы ArrayRef:

module Main where

import Control.Monad
import Control.Monad.ST
import Data.Ref

list = [0..10000]

res = runST $ do
        r <- newSTURef (0::Int)
        forM_ list $ \i -> do
          forM_ list $ \j -> do
            modifySTURef r (+i*j)
        ret <- readSTURef r
        return ret

main = do
  putStr "Result: "
  print res

winger
() автор топика
Ответ на: комментарий от imp

А проблема вроде все же из-за ленивости - при определенном размере памяти хватает, но вылетает StackOverflow

winger
() автор топика
Ответ на: комментарий от yet_another_lor_account

> btw, зачем мучают монадический код, кроме как для ввода/вывода?

Можешь предложить лучший вариант записать то же самое?

Miguel ★★★★★
()
Ответ на: комментарий от yet_another_lor_account

Для оптимизации узких мест, активной работы с mutable массивами и структурами данных, внешними библиотеками и т.д.

winger
() автор топика
Ответ на: комментарий от winger

Еще можно параллелизацию с использованием STM делать, это тоже монада

winger
() автор топика
Ответ на: комментарий от yet_another_lor_account

>btw, зачем мучают монадический код, кроме как для ввода/вывода? Для меня в Хаскелле это всё ещё непонятно.

Ну думать что монады нужны только для IO - это примитивно. Монады это офигенный инструмент если его освоить. И очень удобные они - много для чего.

imp ★★
()
Ответ на: комментарий от yet_another_lor_account

>зачем мучают монадический код

парсер - пример сущности, которая очень хорошо описывается монадически (включая context-dependent with infinite lookahead парсеры вроде Parsec)

jtootf ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.