[Haskell-cafe] Re: Problem with reloading modules in GHC API

Hongmin Fan hongmin.fan.lists at gmail.com
Tue Jul 20 16:39:07 EDT 2010


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!


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<http://www.cse.unsw.edu.au/%7Edons/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
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/haskell-cafe/attachments/20100720/1f4786d5/attachment.html


More information about the Haskell-Cafe mailing list