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

Python - это "-посредственный оператор равенства для Haskell/GHC

Существует ли специальное небезопасное расширение GHC, чтобы спросить, указывают ли две ссылки Haskell на одно и то же местоположение?

Я знаю, что это может сломать ссылочную прозрачность, если она не используется должным образом. Но не должно быть никакого вреда (если я не пропущу что-то), если он используется очень осторожно, в качестве средства для оптимизации путем короткого рекурсивного (или дорогого) обхода данных, например. для реализации оптимизированного экземпляра Eq, например:

instance Eq ComplexTree where
   a == b  = (a `unsafeSameRef` b) || (a `deepCompare` b)

обеспечение deepCompare гарантируется как истина, если unsafeSameRef принимает значение true (но не обязательно наоборот).

EDIT/PS: благодаря ответу, указывающему на System.Mem.StableName, мне также удалось найти документ Растяжение хранилища менеджер: слабые указатели и стабильные имена в Haskell, которые, как оказалось, уже рассматривали эту проблему уже более 10 лет назад...

4b9b3361

Ответ 2

Там есть ошибка, о которой нужно знать:

Уравнение указателя может изменить строгость. I.e., вы можете получить равенство указателя, обозначающее True, когда на самом деле реальный тест равенства будет зацикливаться из-за, например, круговой структуры. Таким образом, равенство указателя разрушает семантику (но вы это знали).

Ответ 3

Я думаю, что StablePointers могут помочь здесь http://www.haskell.org/ghc/docs/6.12.2/html/libraries/base-4.2.0.1/Foreign-StablePtr.html Возможно, это то решение, которое вы ищете:

import Foreign.StablePtr (newStablePtr, freeStablePtr)
import System.IO.Unsafe (unsafePerformIO)

unsafeSameRef :: a -> a -> Bool
unsafeSameRef x y = unsafePerformIO $ do
    a <- newStablePtr x
    b <- newStablePtr y
    let z = a == b
    freeStablePtr a
    freeStablePtr b
    return z;

Ответ 4

Там unpackClosure# в GHC.Prim со следующим типом:

unpackClosure# :: a -> (# Addr#,Array# b,ByteArray# #)

Используя это, вы можете взломать что-то вроде:

{-# LANGUAGE MagicHash, UnboxedTuples #-} 
import GHC.Prim

eq a b = case unpackClosure# a of 
    (# a1,a2,a3 #) -> case unpackClosure# b of 
        (# b1,b2,b3 #) -> eqAddr# a1 b1

И в том же пакете есть интересное название reallyUnsafePtrEquality# типа

reallyUnsafePtrEquality#  :: a -> a -> Int#

Но я не уверен, что такое возвращаемое значение - идя по имени, это приведет к большому скрежет зубов.