codesnippets:hint
Interpreted Haskell code by package hint
- Hint is a package containing a Haskell interpreter built on top of the GHC API.
- example, modified from here, creates a source code file, interprets it and finally deletes it
import Data.List import qualified Control.Monad as M import qualified Language.Haskell.Interpreter as Itpr import qualified System.Directory as Dir import qualified FileSystem as FS main :: IO () main = do Dir.setCurrentDirectory "app" createSomeModule putStrLn "start runInterpreter" r <- Itpr.runInterpreter testHint putStrLn "finished runInterpreter" case r of Left err -> putStrLn $ errorString err Right () -> return () deleteSomeModule createSomeModule :: IO () createSomeModule = FS.processData (FS.DataReader FS.NoInp FS.hGetContents sSomeModuleContent) [ FS.DataWriter (FS.FileOut "SomeModule.hs") FS.hPutStr ] where sSomeModuleContent :: String sSomeModuleContent = "module SomeModule(g, h) where\n\ \\n\ \f = head\n\ \\n\ \g = f [f]\n\ \\n\ \h = f\n\ \\n" deleteSomeModule :: IO () deleteSomeModule = FS.removeFileIfExists "SomeModule.hs" errorString :: Itpr.InterpreterError -> String errorString (Itpr.WontCompile es) = intercalate "\n" (header : map unbox es) where header = "ERROR: Won't compile:" unbox (Itpr.GhcError e) = e errorString e = show e say :: String -> Itpr.Interpreter () say = Itpr.liftIO . putStrLn emptyLine :: Itpr.Interpreter () emptyLine = say "" -- observe that Itpr.Interpreter () is an alias for InterpreterT IO () testHint :: Itpr.Interpreter () testHint = do say "Load SomeModule.hs" Itpr.loadModules ["SomeModule.hs"] emptyLine say "Put the Prelude, Data.Map and *SomeModule in scope" say "Data.Map is qualified as M!" Itpr.setTopLevelModules ["SomeModule"] Itpr.setImportsQ [("Prelude", Nothing), ("Data.Map", Just "M")] emptyLine say "Now we can query the type of an expression" let expr1 = "M.singleton (f, g, h, 42)" say $ "e.g. typeOf " ++ expr1 say =<< Itpr.typeOf expr1 emptyLine say $ "Observe that f, g and h are defined in SomeModule.hs, " ++ "but f is not exported. Let's check it..." exports <- Itpr.getModuleExports "SomeModule" say $ show exports emptyLine say "We can also evaluate an expression; the result will be a string" let expr2 = "length $ concat [[f,g],[h]]" say $ "e.g. eval " ++ show expr2 a <- Itpr.eval expr2 say $ show a emptyLine say "Or we can interpret it as a proper, say, int value!" a_int <- Itpr.interpret expr2 (Itpr.as :: Int) say $ show a_int emptyLine say "This works for any monomorphic type, even for function types" let expr3 = "\\(Just x) -> succ x" say $ "e.g. we interpret " ++ expr3 ++ " with type Maybe Int -> Int and apply it on Just 7" fun <- Itpr.interpret expr3 (Itpr.as :: Maybe Int -> Int) say $ show $ fun (Just 7) emptyLine say "And sometimes we can even use the type system to infer the expected type (eg Maybe Bool -> Bool)!" bool_val <- Itpr.interpret expr3 Itpr.infer `ap` return (Just False) say $ show $ not bool_val emptyLine say "Here we evaluate an expression of type string, that when evaluated (again) leads to a string" res <- do s <- Itpr.interpret "head $ map show [\"Worked!\", \"Didn't work\"]" Itpr.infer Itpr.interpret s Itpr.infer say res emptyLine say "We can also execute statements in the IO monad and bind new names, e.g." let stmts = ["x <- return 42", "print x"] forM_ stmts $ \s -> do say $ " " ++ s Itpr.runStmt s emptyLine
✎
You could leave a comment if you were logged in.
codesnippets/hint.txt · Last modified: by 127.0.0.1
