Я новичок в Haskell (пару месяцев). У меня есть программа Haskell, которая собирает большое выражение DAG (а не дерево, DAG), потенциально глубокое и с несколькими путями слияния (т. Е. Количество разных путей от корня до листьев огромно). Мне нужен быстрый способ протестировать эти dags для равенства. По умолчанию Eq-деривация будет только повторять, исследуя одни и те же узлы несколько раз. В настоящее время это приводит к тому, что моя программа занимает 60 секунд для относительно небольших выражений и даже не заканчивается для более крупных. Профилировщик указывает, что он занят проверкой равенства большую часть времени. Я хотел бы реализовать пользовательский Eq, который не имеет этой проблемы. У меня нет способа решить эту проблему, которая не требует много переписывания. Поэтому я хочу услышать ваши мысли.Экваординация для больших структур DAG в Haskell
Моя первая попытка состояла в том, чтобы узлы дерева «инструмента» с хешем, который я вычисляю поэтапно, используя Data.Hashable.hash
, когда я создаю дерево. Этот подход дал мне простой способ проверить, что две вещи не равны, не заглядывая глубоко в структуру. Но часто в этой DAG из-за путей в объединении DAG структуры действительно равны. Таким образом, хэши равны, и я возвращаюсь к полномасштабному тестированию равенства.
Если бы у меня был способ сделать физическое равенство, тогда многие мои проблемы исчезли бы: если они физически равны, то это все. В противном случае, если хэш отличается, то это все. Только углубляйтесь, если они физически не совпадают, но их хэш соглашается.
Я мог бы также имитировать git и вычислить SHA1 на узел, чтобы решить, равны ли они периоду (нет необходимости рекурсивно). Я знаю, что это помогло бы, потому что, если я позволю равенству быть решенным полностью в терминах хэш-равенства, то программа будет работать в десятки миллисекунд для самых больших выражений. Этот подход также имеет приятное преимущество в том, что если по какой-то причине есть два равных дага, они физически не равны, а являются равными по содержанию, я бы также смог быстро обнаружить его в этом случае. (С идентификаторами Id все равно должен сделать обход в этой точке). Поэтому мне больше нравится семантика.
Этот подход, однако, требует гораздо большей работы, чем просто вызов функции Data.Hashable.hash
, потому что я должен получить ее для каждого варианта типа узла dag. И более того, у меня есть несколько представлений о даге, с немного отличающимися определениями узлов, поэтому мне нужно будет в основном делать эту хэширующую трюкную вещь дважды или более, если я решу добавить больше представлений.
Что вы хотите сделать?
Вы спрашиваете, как определить '(==)' с помощью настраиваемой функции или какая пользовательская функция наилучшим образом соответствует вашим потребностям? Вопрос немного раздутый/запутанный, поскольку он стоит сейчас ... Кстати, я не думаю, что «физическое равенство», как вы знаете, из других языков существует в haskell, вы просто определяете свой 'class Eq a where (==) .... 'и вот оно ... – mb21
@ mb21 Он либо спрашивает, как определить эффективный экземпляр для' Eq', либо как определить структуру данных для своей DAG, для которой эффективный экземпляр по умолчанию для Eq. .. не уверен, какой из двух, и не дал никакого кода, мы можем оказать небольшую помощь. – Bakuriu