В схеме примитив eq?
проверяет, являются ли его аргументы одним и тем же объектом. Например, в следующем списке
(define lst
(let (x (list 'a 'b))
(cons x x)))
Результат
(eq? (car x) (cdr x))
истинно, и, кроме того, оно верно, не заходя в (car x)
и (cdr x)
. Это позволяет вам писать эффективные тесты равенства для структур данных, которые имеют большой доступ.
В Хаскелле все еще возможно? Например, рассмотрим следующую реализацию двоичного дерева
data Tree a = Tip | Bin a (Tree a) (Tree a)
left (Bin _ l _) = l
right (Bin _ _ r) = r
mkTree n :: Int -> Tree Int
mkTree 0 = Tip
mkTree n = let t = mkTree (n-1) in Bin n t t
который имеет доступ на каждом уровне. Если я создам дерево с let tree = mkTree 30
, и я хочу посмотреть, равны ли left tree
и right tree
, наивно мне приходится пересекать более миллиарда узлов, чтобы обнаружить, что они являются одним и тем же деревом, что должно быть очевидно из-за данных совместное использование.
Я не ожидаю, что есть простой способ обнаружить совместное использование данных в Haskell, но я задавался вопросом, что типичные подходы к решению таких проблем, когда было бы хорошо обнаружить совместное использование для целей эффективности (или, например, для обнаружение циклических структур данных).
Есть ли unsafe
примитивы, которые могут обнаружить совместное использование? Есть ли известный способ построения структур данных с явными указателями, чтобы вы могли сравнить равенство указателя?