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 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.