Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
  • Nov 23 2019 14:39
    cblp closed #92
  • Nov 23 2019 14:39
    cblp commented #92
  • Nov 23 2019 14:39
    cblp commented #109
  • Nov 23 2019 14:38

    cblp on gh-pages

    Update link (#109) https://has… (compare)

  • Nov 23 2019 14:37

    cblp on qnikst-patch-1

    (compare)

  • Nov 23 2019 14:37

    cblp on master

    Update link (#109) https://has… (compare)

  • Nov 23 2019 14:37
    cblp closed #109
  • Nov 22 2019 20:25
    qnikst review_requested #109
  • Nov 22 2019 20:25
    qnikst opened #109
  • Nov 22 2019 20:24

    qnikst on qnikst-patch-1

    Update link https://haskell-la… (compare)

  • Nov 18 2019 08:43
    cblp commented #92
  • Nov 17 2019 09:57
    qnikst commented #92
  • Nov 10 2019 09:01

    cblp on gh-pages

    Add The Haskell Phrasebook (compare)

  • Nov 10 2019 09:01

    cblp on master

    Add The Haskell Phrasebook (compare)

  • Oct 31 2019 16:10
    cblp edited #106
  • Oct 31 2019 16:10
    cblp commented #106
  • Oct 31 2019 16:08

    cblp on master

    Add some text from #106 (compare)

  • Oct 30 2019 10:33

    cblp on master

    Add draft of `effects-haskell` … (compare)

  • Oct 30 2019 10:13

    cblp on gh-pages

    Add `sic` to `хаскелит` (compare)

  • Oct 30 2019 10:12

    cblp on master

    Add `sic` to `хаскелит` (compare)

Yuriy Syrovetskiy
@cblp
@arrowd, разве dotToGraph его требует?
Gleb Popov
@arrowd
А, действительно, неправильно прочитал.
Спасибо.
Gleb Popov
@arrowd
Я чет так и не осилил извлечение подграфа по метке узла с помощью graphviz.
Yuriy Syrovetskiy
@cblp
на чём застрял?
Gleb Popov
@arrowd

Сначала я его распарсил в DotGraph a из http://hackage.haskell.org/package/graphviz-2999.20.0.3/docs/Data-GraphViz-Types-Graph.html

Распарсить таким образом, чтобы в a был лейбл я не смог, поэтому пришлось написать функцию, которая проходит по всему графу и матчит ноду с нужными атрибутами. У найденной ноды дернул successors, а это оказались только непосредственные последователи. Т.е. тут тоже чет рекурсивное надо было изобретать, поэтому я забил.
Потом через fgl пробовал, но там оказалось что при восстановлении назад из fgl в дот он какую-то информацию теряет. Не помню уже что именно. Я расстроился и пошел пить.

Gleb Popov
@arrowd
А есть парсер XML а-ля Aeson.TH? Чтобы я ему дататайп, а он сам парсер придумал.
Alexander Tchitchigin
@gabriel-fallen
Я знаю про https://github.com/typeable/xml-isogen но он немного наоборот работает...
nickbeljaev
@nickbeljaev
"Неизлечимая" утечка памяти в простой функции
Yuriy Syrovetskiy
@cblp
отформатируйте как код, пожалуйста
nickbeljaev
@nickbeljaev
Сейчас научусь :) я тут впервой.
Yuriy Syrovetskiy
@cblp
просто вставьте ``` в начале и в конце
почему вы считаете, что функция не должна течь? как вы это доказали?
как минимум для переменной s только строятся задумки (s + 1), но никогда не вычисляются
nickbeljaev
@nickbeljaev
Я это не доказывал, я пытаюсь понять куда течет
g ks (x0,xs,s)
  |x0 == x0' = (x0,s)
  |True = g ks (x0',x0:take 30 xs,(s+1))
  where
  x0' = f xs ks /sum ks

f (x:xs) (k:ks') = x*k + f xs ks'
f _ _ = 0

main = g [2,3,9] (1,[],0)
Чет у меня с форматированием не очень переносы строк исчезли...
Yuriy Syrovetskiy
@cblp
просто вставьте отдельную строку, на которой написаны ```, перед и после текста
как минимум, течёт s
sum тоже линейно память потребляет на некоторых уровнях оптимизации
nickbeljaev
@nickbeljaev
sum проверял - заменял на число - течет
nickbeljaev
@nickbeljaev
s проверил - заменил на число - течет, да и не мог Int счетчик течь, тогда бы вообще все программы текли бы.
Да еще момент - я это в ghci проверяю. Обычно мне удается и там сделать без утечки, но в данный случай заколдованный
nickbeljaev
@nickbeljaev
g ks (x0,xs,s)
  |x0 == x0' = (x0,s)
  |True = seq s $ g ks (x0',x0:take 30 xs,1)
  where
  x0' = f xs ks /14

f (x:xs) (k:ks') = x*k + f xs ks'
f _ _ = 0
так тоже течет x0 x0' должны разрешаться до числа для сравнения в моем понимании, если это не так то понятно куда, но они должны вычисляться?
nickbeljaev
@nickbeljaev
g ks (x0,xs,s)
  |x0 == x0' = (x0,s)
  |True = g ks (x0',x0:take 2 xs,s)
  where
  x0' = f xs ks /sum ks

f (x:xs) (k:ks') = x*k + f xs ks'
f _ _ = 0
практический ответ найден, при take 2 ... take 3 ... утечки нет, при take 4 и более начинается стремительная утечка, получается лишний хвост из более чем 1 элемента влечет утечку (видимо мусорщик считает что этот хвост потом пригодится...) но это мои фантазии.
Alexander Tchitchigin
@gabriel-fallen
@nickbeljaev если Вы запускаете код в GHCi, то он компилируется без оптимизаций, и анализ строгости, уверен, вообще не проводится. В этом случае да, даже Инты "утекают". Не говоря уже про вызовы take. Либо расставьте аннотации строгости руками, либо хотя бы соберите с оптимизацией, для начала.
Yuriy Syrovetskiy
@cblp

@nickbeljaev

s проверил - заменил на число - течет, да и не мог Int счетчик течь, тогда бы вообще все программы текли бы.

в других программах счётчиков или нет, или они строгие

Yuriy Syrovetskiy
@cblp
@nickbeljaev, f = sum . zipWith (+)
@nickbeljaev, да x0 == x0' должно вычислять x0 и x0', x0' приводит к полному вычислению xs и ks, в результате они начинают занимать всю свою память, но не освобождаются, потому что передаются дальше
nickbeljaev
@nickbeljaev
Действительно - после устранения утечки через take потек счетчик, но с этим уже понятнее, окончательный вариант работающий в ghci выглядит так
g ks x0 xs s
  |x0 == x0' = (x0,s)
  |True = seq (s+1) $ g ks x0' (x0:take (length ks -1) xs) ((s+1)::Int)
  where
  x0' = f xs ks /sum ks

f (x:xs) (k:ks') = x*k + f xs ks'
f _ _ = 0
основная засада для меня была в том, что "лишний" хвост xs вызывал утечку, хотя он явно нигде более не используется. Спасибо огромное за участие.
Yuriy Syrovetskiy
@cblp
вместо ((s+1)::Int) лучше написать сигнатуру g
ссылка на xs утекала через задумку x0 : take _ xs
nickbeljaev
@nickbeljaev
Я бы хотел, что бы тип выводился автоматически и правильно - наверное я еще ленивее чем язык :) (s+1)::Int это от паники - без этого тоже работает (пока не переполнит int64 наверное). Насчет пояснения с take _ я не понял - такая правая часть разве возможна?
Yuriy Syrovetskiy
@cblp

без этого тоже работает (пока не переполнит int64 наверное)

наоборот, без этого будет Integer произвольной длины, будет работать корректно и после 2642^{64}

какая правая часть возможна? я использовал подчёркивание как сокращение, если вы про него
nickbeljaev
@nickbeljaev
Последний вариант без этого Int тоже работает на мизере памяти, как и задумывалось в этом алгоритме. Но мне все равно не ясно как "лишний" (то есть нигде и никогда не используемый) хвост xs вызывал переполнение, take 30 xs должен оставлять список в 30 элементов, а все остальное, что там было должно становится клиентом мусорщика и освобождаться, но почему то не становилось и не освобождалось. Возможно, при компиляции с оптимизацией эта проблема самоустранилась бы, но хотелось ручками :)
Yuriy Syrovetskiy
@cblp
для take 30 xs сначала формируется задумка
nickbeljaev
@nickbeljaev
Термин задумка мне не знаком, можно как то другими словами?
nickbeljaev
@nickbeljaev
Кроме того для меня удивительна разница между одним "лишним" и двумя. В последнем варианте если поставить take 3 ... то утечки нет, и это один лишний в xs, но если поставить take 4 ... то начинается зверская утечка (примерно 100М/сек) и это 2 лишних, вот это все, как говорится меня беспокоит - данный пример простой, но столкнись с таким в реальной программе - мало не покажется.
nickbeljaev
@nickbeljaev
Вот еще с take 4 запустил в Hugs - вылетает через несколько секунд по отказу мусорщика, с take 2 мирно работает на мизере памяти, вот похоже все таки сборка мусора "уиновата"
Alexander Tchitchigin
@gabriel-fallen
"Задумка" значит "thunk". Недовычисленное значение. Aka "ленивое". Лежит в куче, занимает память.
Функция f - это dot product, как я понимаю?
seq (s + 1) смысла не имеет, сложение там ни к селу, ни к городу.
nickbeljaev
@nickbeljaev
+1 убрал, действительно - разницы нет, благодарю. Объяснение с "задумкой" не объясняет разницы между коротким хвостом и чуть более длинным, практически установлено, что take 2 take 3 память не расходуют, а с take 4 начинает жрать со страшной силой.
Прошу прощения за мое не владение терминологией, но что значит dot? Функция f фактически является скалярным произведением своих аргументов если это отвечает на Ваш вопрос.
nickbeljaev
@nickbeljaev
Вот еще наблюдение take 10000 жрет память с той же скоростью что и take 4, то есть оставление 2-х и более лишних в хвосте списка фактически означает оставление всего списка в памяти, при этом оставление 0 или 1 лишнего ни к каким негативным проявлениям не приводит.
Alexander Tchitchigin
@gabriel-fallen
Скалярное произведение <=> dot product.
Что там с takeами происходит - нужно разбираться. Но Вам в любом случае нужно понять как работают "задумки" aka thunks и как возникают space leaks. Об этом написано на Haskell wiki и в книге "Parallel and Concurrent Programming in Haskell" (имеется русский перевод).
nickbeljaev
@nickbeljaev
Благодарю за ссылки на книги, на "бытовом уровне" мне понятно что значит отложенное вычисление и почему оно может потреблять памяти больше чем выполненное, а может и не потреблять как например [1..], на уровне компилятора я в этом разбираться не хочу, так как написание компиляторов не моя профессия. Меня пугает отсутствие единообразия результатов в зависимости от количества лишних в списке, то есть тут явно есть бифуркация между 0,1 и остальными числами - хотелось бы понять почему.