|
3 | 3 | [](https://travis-ci.com/haskell-hint/hint)
|
4 | 4 | [](https://hackage.haskell.org/package/hint)
|
5 | 5 |
|
6 |
| -This library defines an Interpreter monad. It allows to load Haskell |
7 |
| -modules, browse them, type-check and evaluate strings with Haskell |
8 |
| -expressions and even coerce them into values. The library is thread-safe |
9 |
| -and type-safe (even the coercion of expressions to values). |
| 6 | +This library defines an Interpreter monad within which you can interpret |
| 7 | +strings like `"[1,2] ++ [3]"` into values like `[1,2,3]`. You can easily |
| 8 | +exchange data between your compiled program and your interpreted program, as |
| 9 | +long as the data has a `Typeable` instance. |
10 | 10 |
|
11 |
| -It is, essentially, a huge subset of the GHC API wrapped in a simpler |
12 |
| -API. |
| 11 | +You can choose which modules should be in scope while evaluating these |
| 12 | +expressions, you can browse the contents of those modules, and you can ask for |
| 13 | +the type of the identifiers you're browsing. |
13 | 14 |
|
14 |
| -Compatibility is kept with the three last major GHC releases. For |
15 |
| -example, if the current version is GHC 8.6, Hint will work on 8.6, 8.4 |
16 |
| -and 8.2. |
| 15 | +It is, essentially, a huge subset of the GHC API wrapped in a simpler API. |
17 | 16 |
|
18 |
| -### Example |
| 17 | +## Limitations |
19 | 18 |
|
20 |
| -Check [example.hs](examples/example.hs) to see a simple but |
21 |
| -comprehensive example (it must be run from the `examples` directory). |
| 19 | +It is possible to run the interpreter inside a thread, but you can't run two |
| 20 | +instances of the interpreter simlutaneously. |
| 21 | + |
| 22 | +GHC must be installed on the system on which the compiled executable is running. |
| 23 | + |
| 24 | +Compatibility is kept with the three last major GHC releases. For example, if |
| 25 | +the current version is GHC 8.6, `hint` will work on 8.6, 8.4 and 8.2. |
| 26 | + |
| 27 | +## Example |
| 28 | + |
| 29 | + {-# LANGUAGE LambdaCase, ScopedTypeVariables, TypeApplications #-} |
| 30 | + import Control.Exception (throwIO) |
| 31 | + import Control.Monad.Trans.Class (lift) |
| 32 | + import Control.Monad.Trans.Writer (execWriterT, tell) |
| 33 | + import Data.Foldable (for_) |
| 34 | + import Data.Typeable (Typeable) |
| 35 | + import qualified Language.Haskell.Interpreter as Hint |
| 36 | + |
| 37 | + -- | |
| 38 | + -- Interpret expressions into values: |
| 39 | + -- |
| 40 | + -- >>> eval @[Int] "[1,2] ++ [3]" |
| 41 | + -- [1,2,3] |
| 42 | + -- |
| 43 | + -- Send values from your compiled program to your interpreted program by |
| 44 | + -- interpreting a function: |
| 45 | + -- |
| 46 | + -- >>> f <- eval @(Int -> [Int]) "\\x -> [1..x]" |
| 47 | + -- >>> f 5 |
| 48 | + -- [1,2,3,4,5] |
| 49 | + eval :: forall t. Typeable t |
| 50 | + => String -> IO t |
| 51 | + eval s = runInterpreter $ do |
| 52 | + Hint.setImports ["Prelude"] |
| 53 | + Hint.interpret s (Hint.as :: t) |
| 54 | + |
| 55 | + -- | |
| 56 | + -- >>> :{ |
| 57 | + -- do contents <- browse "Prelude" |
| 58 | + -- for_ contents $ \(identifier, tp) -> do |
| 59 | + -- when ("put" `isPrefixOf` identifier) $ do |
| 60 | + -- putStrLn $ identifier ++ " :: " ++ tp |
| 61 | + -- :} |
| 62 | + -- putChar :: Char -> IO () |
| 63 | + -- putStr :: String -> IO () |
| 64 | + -- putStrLn :: String -> IO () |
| 65 | + browse :: Hint.ModuleName -> IO [(String, String)] |
| 66 | + browse moduleName = runInterpreter $ do |
| 67 | + Hint.setImports ["Prelude", "Data.Typeable", moduleName] |
| 68 | + exports <- Hint.getModuleExports moduleName |
| 69 | + execWriterT $ do |
| 70 | + for_ exports $ \case |
| 71 | + Hint.Fun identifier -> do |
| 72 | + tp <- lift $ Hint.typeOf identifier |
| 73 | + tell [(identifier, tp)] |
| 74 | + _ -> pure () -- skip datatypes and typeclasses |
| 75 | + |
| 76 | +Check [example.hs](examples/example.hs) for a longer example (it must be run |
| 77 | +from hint's base directory). |
0 commit comments