Подтвердить что ты не робот

Какие преимущества у StableNames превышают trueUnsafePtrEquality #, и наоборот?

data StableName a

Устойчивые имена имеют следующее свойство:  Если sn1:: StableName и sn2:: StableName и sn1 == sn2, то sn1 и sn2 были созданы вызовами makeStableName на одном и том же объекте.

Обратное не обязательно верно: если два устойчивых имени не равны, то объекты, которые они называют, могут по-прежнему быть равными.

reallyUnsafePtrEquality #:: a → a → Int #

reallyUnsafePtrEquality # возвращает, являются ли два объекта в куче GHC одним и тем же объектом. Это действительно небезопасно, потому что сборщик мусора перемещает вещи вокруг, закрывает и т.д. Насколько мне известно, он может возвращать ложные негативы (он говорит, что два объекта не совпадают, но они есть), но не ложные срабатывания (говоря, что они то же самое, когда они не являются).

Оба из них, похоже, выполняют одну и ту же основную вещь: они могут сказать вам, являются ли два объекта определенно одинаковыми, но не являются ли они определенно нет.

Преимущества для StableNames:

  • Они могут быть хешированы.
  • Они менее непропорциональны.
  • Их поведение четко определено и поддерживается.
  • У них нет действительно Unsafe как часть их имени.

Преимущества, которые я могу увидеть для reallyUnsafePtrEquality #:

  • Он может быть вызван непосредственно на объекты, о которых идет речь, вместо того, чтобы создавать отдельные StablesNames.
  • Вам не нужно проходить через функцию ввода-вывода для создания стабильных имен.
  • Вам не нужно сохранять StableNames, поэтому использование памяти ниже.
  • RTS не должен делать все возможное, чтобы заставить StableNames работать, поэтому производительность, по-видимому, лучше.
  • В действительности он действительно работает в имени и # в конце. Hardcore!

Мои вопросы:

  • Я что-то пропустил?

  • Есть ли какой-либо прецедент, когда тот факт, что StableNames является отдельным от объектов, которые они называют, является преимуществом?

  • Является ли еще более точным (с меньшей вероятностью возвращать ложные отрицания), чем другим?

  • Если вам не нужно хэширование, не заботясь о переносимости, и не беспокоитесь, используя что-то под названием reallyUnsafe, есть ли какая-то причина, чтобы предпочесть StableNames над reallyUnsafePtrEquality #?

4b9b3361

Ответ 1

Удерживание StableName объекта не мешает ему собирать мусор, а сам объект вокруг (для использования с reallyUnsafePtrEquality# позже). Конечно, вы можете использовать System.Mem.Weak, но в этот момент почему бы просто не использовать StableName? (На самом деле слабые указатели были добавлены с StableName s.)

Возможность хэшировать их является основным мотиватором для StableName s, как говорится в документации:

Мы не можем построить хэш-таблицу, используя адрес объекта в качестве ключа, потому что объекты будут перемещаться сборщиком мусора, что означает, что после каждой сборки мусора потребуется повторный хэш.

В общем случае, если StableName будет работать для ваших целей, я бы использовал их, даже если вам нужно использовать unsafePerformIO; если вам действительно нужно reallyUnsafePtrEquality#, вы узнаете. Единственный пример, который я могу представить, где reallyUnsafePtrEquality# будет работать, и StableName не будет ускорять дорогостоящий экземпляр Eq:

x == y =
    x `seq` y `seq`
    case reallyUnsafePtrEquality# x y of
        1# -> True
        _  -> slowEq x y

Вероятно, есть другие примеры, о которых я просто не думал, но они не распространены.