2013-09-01 8 views
8

Sto studiando come alcuni linguaggi di programmazione assegnino memoria ai dati strutturati (in questo caso sto studiando array).Come stampare l'indirizzo di memoria di un elenco in Haskell

Sto creando la matrice, come illustrato nella sezione here 3.

import Data.Array.IO 
arr <- newArray (1,10) 37 :: IO (IOArray Int Int) --Sets default to 37 

E quello che sto cercando di fare è stampare l'indirizzo di ciascun elemento di memoria, qualcosa di simile:

Array Start: <dec addr> | <hex addr> --Shows where the array itself is 
Array 1: <dec addr> | <hex addr> --Memory address of the first element 
Array 2: <dec addr> | <hex addr| --Memory address of the second element 

Il problema che ho è che non so come ottenere il valore dell'indirizzo di memoria per un elemento in Haskell.

Esiste una funzione simile a id(object) di Python o Ruby object.object_id?

+3

Non sono sicuro se questo è possibile, ma se lo è, l'indirizzo di memoria in grado di cambiare in qualsiasi momento a causa di delocalizzazione dal garbage collector. –

+0

Sì, ma voglio solo stampare l'indirizzo di memoria in un dato momento quindi non importa se le modifiche successive nell'esecuzione –

+0

c'è un 'reallyUnsafePtrEquals', il' reallyUnsafe' mi fa dubitare che GHC esporrà questa molta magia. – jozefg

risposta

10

È possibile utilizzare il seguente frammento che ho preso in prestito dal pacchetto ghc-heap-view (contiene anche una soluzione alternativa utilizzando foreign import prim):

{-# LANGUAGE MagicHash, BangPatterns #-} 

import GHC.Exts 

-- A datatype that has the same layout as Word and so can be casted to it. 
data Ptr' a = Ptr' a 

-- Any is a type to which any type can be safely unsafeCoerced to. 
aToWord# :: Any -> Word# 
aToWord# a = let !mb = Ptr' a in case unsafeCoerce# mb :: Word of W# addr -> addr 

unsafeAddr :: a -> Int 
unsafeAddr a = I# (word2Int# (aToWord# (unsafeCoerce# a))) 

Questo funziona prima avvolgendo a all'interno di un costruttore Ptr' e poi colata Ptr' a a Word. Poiché il campo a è rappresentato come un puntatore, la parola risultante ora contiene l'indirizzo dell'oggetto. Si applicano le solite avvertenze: questo è sicuro, GHC-specifica, rompe trasparenza referenziale, ecc

Testing:

main :: IO() 
main = do 
    arr <- newListArray (1,10) [1,2..] :: IO (IOArray Int Int) 
    a1 <- readArray arr 1 
    a2 <- readArray arr 2 
    a1' <- readArray arr 1 

    putStrLn $ "a1 : " ++ (show . unsafeAddr $! a1) 
    putStrLn $ "a1 : " ++ (show . unsafeAddr $! a1) 
    putStrLn $ "a2 : " ++ (show . unsafeAddr $! a2) 
    putStrLn $ "a2 : " ++ (show . unsafeAddr $! a2) 
    putStrLn $ "a1': " ++ (show . unsafeAddr $! a1') 

uscita:

a1 : 16785657 
a1 : 16785657 
a2 : 16785709 
a2 : 16785709 
a1': 16785657 

nota che si dovrebbe usare unsafeAddr con $!, in caso contrario riceverai un indirizzo di un thunk che verrà valutato su a anziché sullo stesso oggetto a:

let a = 1 
     b = 2 
     c = a + b 

    putStrLn $ "c: " ++ (show . unsafeAddr $ c) 
    putStrLn $ "c: " ++ (show . unsafeAddr $! c) 
    putStrLn $ "c: " ++ (show . unsafeAddr $! c) 

uscita:

c: 9465024 
c: 9467001 
c: 9467001 
+1

Idea pulita! Possibili miglioramenti: Word sarebbe un tipo finale migliore di Int (di solito consideriamo gli indirizzi come non negativi).Se stavate per impacchettare questo probabilmente vorreste fare una versione che 'seq's' a' prima di controllare l'indirizzo. –

+1

Anche i tag del puntatore vengono stampati qui, dovrebbero essere mascherati. –

+0

@NathanHowell Fare questo in Haskell è problematico perché la larghezza del tag dipende dalla piattaforma. 'ghc-heap-view' implementa' aToWord # 'come primop per questo motivo. –

Problemi correlati