haskellmemoryfunctional-programmingheap-memorytooling

Is there a way to obtain an accurate description of the heap state?


I was fascinated by this video on visualization of Haskell heap, but unfortunately I haven't been able to use ghc-vis. My understanding is that it is too old now. (Feel free to suggest how to actually compile it here if you think the tool is still usable on a modern install.)

Is there some other package that allows similar visualization, or at least a text-based inspection of the heap?

For instance, say I type the following in ghci

λ> data Person = Person { name :: String,
                          surname :: String,
                          age :: Int
                        } deriving Show

λ> baron = Person { name = "Cosimo",
                    surname = "Piovasco di Rondò",
                    age = 12 }
λ> oldBaron = baron { age = 65 }
λ> brother = baron { name = "Biagio" }
λ> baron
Person {name = "Cosimo", surname = "Piovasco di Rond\242", age = 12}
λ> oldBaron 
Person {name = "Cosimo", surname = "Piovasco di Rond\242", age = 65}
λ> brother 
Person {name = "Biagio", surname = "Piovasco di Rond\242", age = 12}

My understanding is that

Is there a tool/package that can show me all of this?


I know that the :sprint command can help me visualize lazyiness, for instance, before evaluating the three names in the snipet above, I could do

λ> :sprint baron 
baron = <Person> _ _ 12
λ> :sprint oldBaron 
oldBaron = _
λ> :sprint brother  
brother = _

and see that nothing has been computed yet; then, if I evaluate only brother, I can repeat the commands above and I'll get

λ> :sprint baron 
baron = <Person> _ "Piovasco di Rondò" 12
λ> :sprint oldBaron 
oldBaron = _
λ> :sprint brother  
brother = <Person> "Biagio" "Piovasco di Rondò" 12

which does reveal something along the lines of what I'm asking, becuase it shows that surname brother points effectively to surname baron.


Solution

  • The svgcairo issue you linked to in your other comment has a link to a PR with the fix. It just hasn't been merged by the maintainer. The beauty of open source is that you can apply the fix for your own sake.

    Here are the steps I took to get ghc-vis running with GHC 9.6 (and for completeness, I am on Ubuntu 24.04, there appears to be at least one additional fix to apply to work on MacOS).

    Fixes and installation

    Get svgcairo

    1. git clone https://github.com/gtk2hs/svgcairo

    2. Edit svgcairo.h to rename librsvg/librsvg-features.h to librsvg/rsvg-features.h

    3. Edit svgcairo.cabal to remove the upper bound on Cabal

    Get ghc-vis to install it together with the locally fixed svgcairo (maybe there is a more direct way to build ghc-vis while using a local svgcairo, but I don't know it):

    1. git clone https://github.com/def-/ghc-vis

    2. echo "packages: ghc-vis svgcairo" > cabal.project (from the directory containing both ghc-vis and svgcairo)

    3. cabal install --env . --lib ghc-vis --with-compiler=ghc-9.6


    Sample ghc-vis usage

    Start ghc-vis (make sure to use the version of ghc(i) that matches the installation)

    ghci-9.6
    ghci> :script ghc-vis/ghci
    ghci> :vis
    # a window opens
    

    Visualize a value:

    ghci> let a = [1..3]
    ghci> :view a
    

    (At this point I ran into another error due to a missing dot command, which was fixed by apt install graphviz.)

    The window now displays a graph:

    screenshot of ghc-vis window

    Press v to switch to the "list view" (the colorful boxes in the ghc-vis user guide), and back to the graph view.

    In the graph view, you can click AP and Thunk nodes to force evaluation. In the list view, you can click t_ nodes to force evaluation.