LINUX.ORG.RU

проблемы с Haskell


0

0
<тут длинная история про то, как я начал писать прогу на хаскелле, а она...>

В общем когда я выискивал суть проблемы, то увидел:

x :: [Double]
x = take 5000000 ([1..])

main = do
print (fromIntegral (length x))
print (sum x)

не быстро.. да... но работает.. нормально

x :: [Double]
x = take 5000000 ([1..])

main = do
print ((sum x) / (fromIntegral (length x)))

работает долго и падает с нехваткой стека. Даже, если выставить стек в 50МБ....

Наверняка я что-то фундаментально в хаскелле упустил. Но вот что?
★★★★★
Ответ на: комментарий от Miguel
Только что проверил первый вариант. Упало, как и следовало ожидать.
Miguel ★★★★★
()
ммм....
1) почему не должно?
2) как правильно найти среднее арифметическое списка Double?
Как только не пробовал... и через foldl' и... в общем. Как?
Waterlaz ★★★★★
() автор топика
Ответ на: комментарий от sf
import Data.List
x :: [Double]
x = take 500000 [1..]

average xs = foldl' count (0, 0) xs
      where count acc x = (fst acc + x, snd acc + 1)

main = do
	     print (average x)

-- мб не красиво, но должно же работать.... 
Waterlaz ★★★★★
() автор топика
Ответ на: комментарий от Waterlaz
Да.. вычисляет не среднее, а пару (сумма ряда, количество элементов)
Waterlaz ★★★★★
() автор топика
Ответ на: комментарий от Waterlaz
import Data.List

x' :: [Double] x' = take 5000000 [1..]

average xs = foldl' count (0, 0) xs where count (!s, !l) !x = (s + x, l + 1)

main = print (average x')

-- -XBangPatterns rulez

sf ★★★
()
Ответ на: комментарий от Waterlaz
> мб не красиво, но должно же работать

Ленивость. Получается длинное выражение из плюсов и чисел. Естественно, оно падает.

Miguel ★★★★★
()
Ответ на: комментарий от Waterlaz
Хм. Видишь ли, есть разные понятия строгости. Грубо говоря, foldl' гарантирует, что значение отлично от жопы (то есть (_|_) - видел такое обозначение?) Для случая, когда значение - простой тип вроде Double, этого достаточно, кроме жопы там есть только обычные значения. Для случая, когда мы считаем пару, он не гарантирует, что значение отлично от ((_|_), (_|_)) - а значит, откладывает вычисление элементов пары. Грубо говоря, foldl' убеждается, что пара, полученная на очередном этапе - именно пара, а не, например, ошибка; дальше он не лезет.

В Хаскеле нет способа форсировать вычисление на всю глубину, если она заранее неизвестна. Стандартные функции типа seq и foldl' форсируют лишь один уровень вычисления.

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