[Haskell-cafe] Re: Problem with reloading modules in GHC API
Andy Stewart
lazycat.manatee at gmail.com
Tue Jul 20 21:29:41 EDT 2010
Hongmin Fan <hongmin.fan.lists at gmail.com> writes:
> Thanks Andy! Yes, I do need the second approach you listed here. I think the plugin package actually
> uses GHC API to load
> too.
>
> My problem here is more technical than theoretical. The type safety isn't the primary issue for me,
> because I'm trying to
> implement a certain genetic programming system (there is some papers like this one:
> http://citeseerx.ist.psu.edu/viewdoc/
> summary?doi=10.1.1.98.7686), which generates functions that I'm going to dynamically evaluate. I'm
> hoping to use GHC API to
> avoid writing my own evaluator. The func generation component actually is designed to generate
> functions of the specific
> type, so no worries about type safty.
>
> I'm looking for a clean/correct way to use GHC API to reload the module, maybe there is some option
> I should set but I
> didn't? Being new to Haskell, the source code for GHCi isn't so accessible... Thanks!
If you want dynamic evaluation, you can try hint : Runtime Haskell interpreter (GHC API wrapper)
At http://hackage.haskell.org/package/hint
Cheers,
-- Andy
>
> On Tue, Jul 20, 2010 at 1:01 AM, Andy Stewart <lazycat.manatee at gmail.com> wrote:
>
> Hi Hongmin,
>
> I think you're looking for how to hot-swap Haskell program.
>
> There are two approach to reach target:
>
> 1) Source-Code level:
> Recompile source code to build new execute cache file, if re-compile
> successful, use executeFile to switch new entry. You perhaps need use
> Binary instance to save/restore state between re-launch new execute
> file.
>
> 2) Dynamic Linking object code.
> Compile plugins code to object file, the use .o and .hi file to
> dynamic linking object code to running Haskell application.
> Because .hi file have type/depend information, we can do type-check
> when dynamic linking .o file.
>
> First way is simpler, but you perhaps will lost state after reboot,
> because you can't serialize state (such as FFI) sometimes.
>
> Second way is more complicated, but you can present all state when hot-swapping.
>
> Looks you need second way, from your code, that's wrong, you can't
> dynamic link object file without type-check, and expect everything will
> be fine.
> If you don't type-check when linking code, it's very dangerous, it willl *crash* your
> program once type mismatch or runtime error occur.
>
> Infact, Don Stewart has implement a complete solution to dynamic
> linking in Haskell program, at
> http://hackage.haskell.org/package/plugins-1.4.1
> Unfortunately, it's broken with ghc-6.12.x
>
> Before Don fix plugins package, i recommend you read Don's new paper
> (http://www.cse.unsw.edu.au/~dons/papers/dons-phd-thesis.pdf)
> You will know every detail that how to dynamic extension Haskell
> program.
>
> Hope above will help you. :)
>
> -- Andy
>
> Hongmin Fan <hongmin.fan.lists at gmail.com> writes:
>
> > Hi,
> >
> > I'm using GHC API to dynamically load some module, and evaluate it; and later change the
> content of
> > the module, and
> > re-evaluate it. But I found unless I delete the object file created by previous compilation,
> the
> > module seems not reloaded.
> > I have set ghcLink = LinkInMemory as an older post suggested
> >
> > To illustrate what I'm saying, here is a piece of code (sorry for any naivety in the code, new
> to
> > Haskell too)
> >
> > import System.IO (IOMode(..),hClose,hPutStr,openFile)
> > import Directory (removeFile)
> > import GHC
> > import GHC.Paths
> > import DynFlags
> > import Unsafe.Coerce
> >
> > src_file = "Target.hs"
> > obj_file = "Target.o"
> >
> > main = do
> > writeTarget "arg"
> > func0 <- compileTarget
> > putStrLn $ show $ func0 2
> >
> > writeTarget "arg*2"
> > func1 <- compileTarget
> > putStrLn $ show $ func1 2
> >
> > writeTarget input = do
> > -- removeFile obj_file `catch` (const $ return ()) -- uncomment this line to have correct
> results
> > h <- openFile src_file WriteMode
> > hPutStr h "module Target (Target.target) where\n"
> > hPutStr h "target::Double -> Double\n"
> > hPutStr h "target arg = \n "
> > hPutStr h input
> > hClose h
> >
> > compileTarget =
> > defaultErrorHandler defaultDynFlags $ do
> > func <- runGhc (Just libdir) $ do
> > -- setup dynflags
> > dflags <- getSessionDynFlags
> > setSessionDynFlags dflags { ghcLink = LinkInMemory }
> >
> > -- load target module
> > target <- guessTarget src_file Nothing
> > setTargets [target]
> > r <- load LoadAllTargets
> > case r of
> > Failed -> error "Compilation failed"
> > Succeeded -> do
> > m <- findModule (mkModuleName "Target") Nothing
> > -- set context and compile
> > setContext [] [m]
> > value <- compileExpr ("Target.target")
> > do
> > let value' = (unsafeCoerce value) :: Double -> Double
> > return value'
> > return func
> >
> > The code basically write to a Haskell source file twice with different content, and hoping to
> get
> > different results, but
> > unless I uncomment the line with removeFile, the output of 2 runs are the same; using 'touch'
> to
> > touch the source file being
> > written between 2 runs also gives the correct results. So maybe caused by some caching
> mechanism?
> >
> > I'm using GHC 6.12.1 in Ubuntu 10.04. I have this workaround of deleting the obj file, but I'm
> > wondering the "correct" way
> > of doing it. Did some search on GHC API, but never got something relevant.
> >
> > Thanks,
> > Hongmin
> >
> > _______________________________________________
> > Haskell-Cafe mailing list
> > Haskell-Cafe at haskell.org
> > http://www.haskell.org/mailman/listinfo/haskell-cafe
>
> _______________________________________________
> Haskell-Cafe mailing list
> Haskell-Cafe at haskell.org
> http://www.haskell.org/mailman/listinfo/haskell-cafe
More information about the Haskell-Cafe
mailing list