[ANN] heap-console - Haskell

Welcome to the Functional Programming Zulip Chat Archive. You can join the chat here.

TheMatten

I was working on this tool for inspecting values at runtime recently - https://hackage.haskell.org/package/heap-console
Basically, it let's you pause at presence of special combinators, starting console which you can use to inspect and force custom bindings.
If anyone wants some more powerful alternative to traceShow, you can give it a go - personally I'm excited to try it out in compiler-ish stuff where I often want to explore big, nested values to find out what went wrong. :smile:

Georgi Lyubenov // googleson78

Bindings can be automatically created with functions like inspectD what does Bindings mean here?

TheMatten

They're just values bound to some names inside of console
Will make it more clear in docs, thanks for mentioning!

Georgi Lyubenov // googleson78

so if I use inspectD 42 what binding is automatically created? it might be a good idea to show this in the example for inspectD

TheMatten

Yeah, it gets bound to it as mentioned in inspects description

TheMatten

I guess I will move longer descriptions to D versions and add queries for it in examples, thanks!

Georgi Lyubenov // googleson78

ah I guess what was confusing me is that I expected the inspectD version to be the one creating bindings, as opposed to inspect, because this is the first time inspectD is mentioned in the docs and it's in the context of bindings

Georgi Lyubenov // googleson78

something that would be really cool is a pattern synonym that you can add to a particular case match and get all the bindings from that case match in the "console" automatically

Georgi Lyubenov // googleson78

but I'm not sure this is possible without a source plugin or something

TheMatten

D is for Data - they otherwise behave in the same way

TheMatten

Georgi Lyubenov // googleson78 said:

something that would be really cool is a pattern synonym that you can add to a particular case match and get all the bindings from that case match in the "console" automatically

That's a cool idea - maybe I could make quasiquoter like

[i| ... |]

that works in both expressions and patterns

Georgi Lyubenov // googleson78

well I kind of realised my original suggestion is easily doable as is, no? the issue is more that you need a way to access the "fields" of the constructor if it's not a record type

Georgi Lyubenov // googleson78

e.g.

pattern InspectD :: Data a => a -> a
pattern InspectD x <- (inspectD -> x)

and now you can write

data Person = Person {name :: String}
x :: Person
case x of
  InspectD (Person ...) -> ...

and

it.name
TheMatten

Yeah - I thought you mean binding variables introduced by pattern

TheMatten

though I wonder whether it's big win over (inspectD -> Person ...) :smile:

Georgi Lyubenov // googleson78

yeah I guess the only thing missing is reusing the actual names you've bound in the program

TheMatten

Yeah, that's hard without TH or plugin

Vladimir Ciobanu

This is super cool. Looking forward to trying it out in a project!

TheMatten

Thank you guys for feedback! One question - do you think it would be better to preserve all bound values between console runs? (not just those bound with evidence-like combinators)

Vladimir Ciobanu

I would say no, as it could get expensive in some apps. Having the ability to optionally do that might be cool, but I'd default to no.

TheMatten

Hmm, thing is, this basically only changes behaviour of it and binds created in console
I guess binding lots of things with evidence is more probable, and in that case, I could implement the opposite - cleaning of binds when closing console

TheMatten

But if that's going to be an option, I probably need to start thinking about persistent configuration - how would that work in app that may be tested through cabal run or from completely different location?

Vladimir Ciobanu

I have no idea what black magic you use for evidence, but couldn't you use that to have a function that turns a flag on or off?

Torsten Schmits

it's an IORefcontaining a Map!

Torsten Schmits

so to answer @Vladimir Ciobanu 's question: yes!

Vladimir Ciobanu

Oh, lol. An actual global variable. Neato. So why not stick the option in there, and provide on/off helpers.

TheMatten

I'm not that worried about adding bindings based on control flow - but I feel more uneasy about doing so with configuration :sweat_smile:

TheMatten

Not like this is meant for something other than debugging, but still

TheMatten

Version on GitLab now preserves state across console runs - and I've added option to clean bindings on console exit (now it can be at least slightly useful)

TheMatten

BTW, what do you think about searching for .heap-console conf file in location of executable?

TheMatten

And :save command that dumps settings there

Georgi Lyubenov // googleson78

(also, I'd recommend in the location of the executable, and also recursively in parents, so it's easier to use with something like stack)

TheMatten
heap-console> :show
cleanOnExit = False
depth = 16
prompt = "heap-console> "
showTypes = False
strict = False
TheMatten

Georgi Lyubenov // googleson78 said:

(also, I'd recommend in the location of the executable, and also recursively in parents, so it's easier to use with something like stack)

Sounds reasonable - will try it

TheMatten
> inspection
[Entering heap-view - use `:help` for more information]
[Reading configuration at `/home/thematten/.heap-console`]
heap-console> :show
cleanOnExit = False
depth = 100
prompt = "heap-console> "
showTypes = False
strict = False
heap-console> :set depth 42
heap-console> :set prompt "?> "
?> :show
cleanOnExit = False
depth = 42
prompt = "?> "
showTypes = False
strict = False
?> :saveConfig
Saved configuration to `/home/thematten/.heap-console`
?> ^D
[Exiting heap-view]
> ^D
Leaving GHCi.
$> cat ~/.heap-console
cleanOnExit = False
depth = 42
prompt = "?> "
showTypes = False
strict = False
Georgi Lyubenov // googleson78

prompt = "heap-console> "
hehe, nice

Georgi Lyubenov // googleson78

this "global" heap-console config seems to have turned out pretty nice for usage

Georgi Lyubenov // googleson78

put a universal one in home and forget about it

TheMatten

Next up on list are Generic support and refactoring of console - and I should really start writing tests :sweat_smile:

TheMatten

I've pushed new version on GitLab with refactored console that should be easier to extend and should make it easier to support auto-complete - once I finish Generic I'll make a new release and start working on tests

TheMatten

@Georgi Lyubenov // googleson78 I've just realized why Generic may be slightly more problematic - it hides actual laziness of input value, so lazy indexing isn't very informative

TheMatten

I guess I'll mention it as a drawback, similarly to problems with non-Data combinators