<span class="Apple-style-span" style="font-family: arial, sans-serif; font-size: 13px; border-collapse: collapse; "><div>I'm trying to receive small segments of Haskell code over a socket, and be able to evaluate them in real time in GHCI.</div>
<div>I've already downloaded Hint and have run the test code, and it's working great. I'm also using the socket server code from Ch.27 of "Real World Haskell"</div><div>and that is working well also. </div>
<div><br></div><div> directly below is the function from the socket server code that handles the incoming messages.</div><div> Instead of doing this: "putStrLn msg"... I want to send whatever is captured in "msg" to the GHC interpreter that is used in the Hint code, something like this: "eval msg".</div>
<div> I'm not sure how to combine both of these functionalities to get them to work with each other..</div><div><br></div><div><div> -- A simple handler that prints incoming packets</div><div> plainHandler :: HandlerFunc</div>
<div> plainHandler addr msg = </div><div> putStrLn msg </div></div><div><br></div><div><br></div><div>Below is the full code for the socket server, then below that is "SomeModule" used in the Hint example test below that.</div>
<div><br></div><div>-- file: ch27/syslogserver.hs</div><div>import Data.Bits</div><div>import Network.Socket</div><div>import Network.BSD</div><div>import Data.List</div><div><br></div><div>type HandlerFunc = SockAddr -> String -> IO ()</div>
<div><br></div><div>serveLog :: String -- ^ Port number or name; 514 is default</div><div> -> HandlerFunc -- ^ Function to handle incoming messages</div><div> -> IO ()</div><div>
serveLog port handlerfunc = withSocketsDo $</div><div> do -- Look up the port. Either raises an exception or returns</div><div> -- a nonempty list. </div><div> addrinfos <- getAddrInfo </div><div> (Just (defaultHints {addrFlags = [AI_PASSIVE]}))</div>
<div> Nothing (Just port)</div><div> let serveraddr = head addrinfos</div><div><br></div><div> -- Create a socket</div><div> sock <- socket (addrFamily serveraddr) Datagram defaultProtocol</div>
<div><br></div><div> -- Bind it to the address we're listening to</div><div> bindSocket sock (addrAddress serveraddr)</div><div><br></div><div> -- Loop forever processing incoming data. Ctrl-C to abort.</div>
<div> procMessages sock</div><div> where procMessages sock =</div><div> do -- Receive one UDP packet, maximum length 1024 bytes,</div><div> -- and save its content into msg and its source</div>
<div> -- IP and port into addr</div><div> (msg, _, addr) <- recvFrom sock 1024</div><div> -- Handle it</div><div> handlerfunc addr msg</div><div> -- And process more messages</div>
<div> procMessages sock</div><div><br></div><div>-- A simple handler that prints incoming packets</div><div>plainHandler :: HandlerFunc</div><div>plainHandler addr msg = </div><div> putStrLn msg</div><div>
</div><div><br></div><div>-- main = serveLog "8008" plainHandler</div><div>----------------------------------------------------------------------------------------------------------------</div><div><br></div>
<div><div>module SomeModule(g, h) where</div><div><br></div><div>f = head</div><div><br></div><div>g = f [f]</div><div><br></div><div>h = f</div><div><br></div><div>----------------------------------------------------------------------------------------------------------------</div>
</div><div><br></div><div><div>import Control.Monad</div><div>import Language.Haskell.Interpreter</div><div><br></div><div>main :: IO ()</div><div>main = do r <- runInterpreter testHint</div><div> case r of</div>
<div> Left err -> printInterpreterError err</div><div> Right () -> putStrLn "that's all folks"</div><div><br></div><div>-- observe that Interpreter () is an alias for InterpreterT IO ()</div>
<div>testHint :: Interpreter ()</div><div>testHint =</div><div> do</div><div> say "Load SomeModule.hs"</div><div> loadModules ["SomeModule.hs"]</div><div> --</div><div> say "Put the Prelude, Data.Map and *SomeModule in scope"</div>
<div> say "Data.Map is qualified as M!"</div><div> setTopLevelModules ["SomeModule"]</div><div> setImportsQ [("Prelude", Nothing), ("Data.Map", Just "M")]</div>
<div> --</div><div> say "Now we can query the type of an expression"</div><div> let expr1 = "M.singleton (f, g, h, 42)"</div><div> say $ "e.g. typeOf " ++ expr1</div><div>
say =<< typeOf expr1</div><div> --</div><div> say $ "Observe that f, g and h are defined in SomeModule.hs, " ++</div><div> "but f is not exported. Let's check it..."</div>
<div> exports <- getModuleExports "SomeModule"</div><div> say (show exports)</div><div> --</div><div> say "We can also evaluate an expression; the result will be a string"</div><div>
let expr2 = "length $ concat [[f,g],[h]]"</div><div> say $ concat ["e.g. eval ", show expr1]</div><div> a <- eval expr2</div><div> say (show a)</div><div> --</div><div> say "Or we can interpret it as a proper, say, int value!"</div>
<div> a_int <- interpret expr2 (as :: Int)</div><div> say (show a_int)</div><div> --</div><div> say "This works for any monomorphic type, even for function types"</div><div> let expr3 = "\\(Just x) -> succ x"</div>
<div> say $ "e.g. we interpret " ++ expr3 ++</div><div> " with type Maybe Int -> Int and apply it on Just 7"</div><div> fun <- interpret expr3 (as :: Maybe Int -> Int)</div>
<div> say . show $ fun (Just 7)</div><div> --</div><div> say "And sometimes we can even use the type system to infer the expected type (eg Maybe Bool -> Bool)!"</div><div> bool_val <- (interpret expr3 infer `ap` (return $ Just False))</div>
<div> say (show $ not bool_val)</div><div> --</div><div> say "Here we evaluate an expression of type string, that when evaluated (again) leads to a string"</div><div> res <- interpret "head $ map show [\"Worked!\", \"Didn't work\"]" infer >>= flip interpret infer</div>
<div> say res</div><div><br></div><div><br></div><div>say :: String -> Interpreter ()</div><div>say = liftIO . putStrLn</div><div><br></div><div>printInterpreterError :: InterpreterError -> IO ()</div><div>printInterpreterError e = putStrLn $ "Ups... " ++ (show e)</div>
</div></span>