daj
daj

Reputation: 7183

Automatically reloading variable state into GHCi when re-loading a file

When I'm developing some data analyses pipelines in haskell, it often would be useful to preload variable state into GHCi upon loading.

What I end up doing now is copy and pasting parts of a script line-by-line in emacs just to test and check the output of some intermediate processing. I can't even bulk copy-paste code because the line breaks don't get transferred (at least in emacs Interactive-Haskell mode)

Is there a way to do this?

EDIT: simply loading/reloading a .hs file doesn't do the trick because afaik there's no way to have "<-" bindings at the top level.

Upvotes: 3

Views: 766

Answers (2)

bennofs
bennofs

Reputation: 11963

I suggest you take a look at foreign-store. It allows you to refer to variables by numbers, which persists through reloads. Here is an example:

λ: :set -XScopedTypeVariables 
λ: import Foreign.Store
λ: st <- newStore "example"
Loading package foreign-store-0.2 ... linking ... done.
λ: readStore st
"example"
λ: st
Store 0
λ: :r
Ok, modules loaded: none.
λ: st
<interactive>:8:1:
    Not in scope: ‘st’
    Perhaps you meant ‘fst’ (imported from Prelude)
λ: Just (st :: Store String) <- lookupStore 0
λ: readStore st
"example"

Alternatively, you can also put all your definitions in a single hs file and only reload that. You can use unsafePerformIO to get around the restriction that you cannot use <- at the top-level. I think that is ok in this case, since your only using it for interactive anyway:

module Example where

import System.IO.Unsafe

example :: String 
example = "example"

file :: String
file = unsafePerformIO $ readFile "/tmp/example.hs"

Upvotes: 3

AJF
AJF

Reputation: 11913

There are two main ways to do this:

  • Use the :l [filename] GHCi command to reload a file without exiting GHCi.
  • Write the variables in your ~/.ghci file, which will be loaded when GHCi is opened.

If you don't know what to put into ~/.ghci, here's what I have in mine:

:set prompt "\955 "
:set prompt2 "| "

:def hoogle \x -> return $ ":!hoogle --info \"" ++ x ++ "\""

let f `on` x = \a b -> (f a) `x` (f b)
let break (f,g) = \a -> (f a, f g)

Upvotes: 0

Related Questions