hint: Runtime Haskell interpreter (GHC API wrapper)

[ bsd3, compilers-interpreters, language, library ] [ Propose Tags ]

This library defines an Interpreter monad. It allows to load Haskell modules, browse them, type-check and evaluate strings with Haskell expressions and even coerce them into values. The library is thread-safe and type-safe (even the coercion of expressions to values). It is, essentially, a huge subset of the GHC API wrapped in a simpler API.


[Skip to Readme]

Downloads

Maintainer's Corner

Package maintainers

For package maintainers and hackage trustees

Candidates

Versions [RSS] 0.1, 0.2, 0.2.1, 0.2.2, 0.2.4, 0.2.4.1, 0.3.0.0, 0.3.1.0, 0.3.2.0, 0.3.2.1, 0.3.2.2, 0.3.2.3, 0.3.3.0, 0.3.3.1, 0.3.3.2, 0.3.3.3, 0.3.3.4, 0.3.3.5, 0.3.3.6, 0.3.3.7, 0.4.0.0, 0.4.1.0, 0.4.2.0, 0.4.2.1, 0.4.2.2, 0.4.2.3, 0.4.3, 0.5.0, 0.5.1, 0.5.2, 0.6.0, 0.7.0, 0.8.0, 0.9.0, 0.9.0.1, 0.9.0.2, 0.9.0.3, 0.9.0.4, 0.9.0.5, 0.9.0.6, 0.9.0.7, 0.9.0.8 (info)
Change log CHANGELOG.md
Dependencies base (>=4 && <5), directory, exceptions (>=0.10 && <0.11), filepath, ghc (>=8.4 && <8.11), ghc-boot, ghc-paths, random, temporary, transformers, unix (>=2.2.0.0) [details]
License BSD-3-Clause
Author The Hint Authors
Maintainer mvdan@mvdan.cc
Category Language, Compilers/Interpreters
Home page https://github.com/haskell-hint/hint
Source repo head: git clone https://github.com/haskell-hint/hint
Uploaded by gelisam at 2020-04-25T16:50:12Z
Distributions Arch:0.9.0.6, Debian:0.9.0.3, Fedora:0.9.0.7, FreeBSD:0.4.2.3, LTSHaskell:0.9.0.8, NixOS:0.9.0.8, Stackage:0.9.0.8
Reverse Dependencies 39 direct, 194 indirect [details]
Downloads 74049 total (201 in the last 30 days)
Rating 2.5 (votes: 4) [estimated by Bayesian average]
Your Rating
  • λ
  • λ
  • λ
Status Docs uploaded by user
Build status unknown [no reports yet]

Readme for hint-0.9.0.3

[back to package description]

hint

Build Status Hackage

This library defines an Interpreter monad within which you can interpret strings like "[1,2] ++ [3]" into values like [1,2,3]. You can easily exchange data between your compiled program and your interpreted program, as long as the data has a Typeable instance.

You can choose which modules should be in scope while evaluating these expressions, you can browse the contents of those modules, and you can ask for the type of the identifiers you're browsing.

It is, essentially, a huge subset of the GHC API wrapped in a simpler API.

Limitations

It is possible to run the interpreter inside a thread, but you can't run two instances of the interpreter simlutaneously.

GHC must be installed on the system on which the compiled executable is running.

Compatibility is kept with the three last major GHC releases. For example, if the current version is GHC 8.6, hint will work on 8.6, 8.4 and 8.2.

Example

{-# LANGUAGE LambdaCase, ScopedTypeVariables, TypeApplications #-}
import Control.Exception (throwIO)
import Control.Monad.Trans.Class (lift)
import Control.Monad.Trans.Writer (execWriterT, tell)
import Data.Foldable (for_)
import Data.Typeable (Typeable)
import qualified Language.Haskell.Interpreter as Hint

-- |
-- Interpret expressions into values:
--
-- >>> eval @[Int] "[1,2] ++ [3]"
-- [1,2,3]
-- 
-- Send values from your compiled program to your interpreted program by
-- interpreting a function:
--
-- >>> f <- eval @(Int -> [Int]) "\\x -> [1..x]"
-- >>> f 5
-- [1,2,3,4,5]
eval :: forall t. Typeable t
     => String -> IO t
eval s = runInterpreter $ do
  Hint.setImports ["Prelude"]
  Hint.interpret s (Hint.as :: t)

-- |
-- >>> :{
-- do contents <- browse "Prelude"
--    for_ contents $ \(identifier, tp) -> do
--      when ("put" `isPrefixOf` identifier) $ do
--        putStrLn $ identifier ++ " :: " ++ tp
-- :}
-- putChar :: Char -> IO ()
-- putStr :: String -> IO ()
-- putStrLn :: String -> IO ()
browse :: Hint.ModuleName -> IO [(String, String)]
browse moduleName = runInterpreter $ do
  Hint.setImports ["Prelude", "Data.Typeable", moduleName]
  exports <- Hint.getModuleExports moduleName
  execWriterT $ do
    for_ exports $ \case
      Hint.Fun identifier -> do
        tp <- lift $ Hint.typeOf identifier
        tell [(identifier, tp)]
      _ -> pure ()  -- skip datatypes and typeclasses

Check example.hs for a longer example (it must be run from hint's base directory).