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