I have an application where, for various reasons, I need to run arbitrary, user supplied code. (SafeHaskell makes this nice and secure). I've looked at the plugins package, which is really nice for loading from a .hi file on disc.
However, for my program design, it would be ideal if I could store these user programs in a database, then directly compile them to functions which I can use in my program.
So, if the function I'm compiling has the following type:
someFunction :: MyIn -> MyOut
I'm looking to write some function that will generate that function from a string:
hotCompile :: String -> IO (MyIn -> MyOut)
where string contains the haskell code code for "someFunction".
Does anybody know if there's a way to do this, preferably using the plugins package? I have come across the GHC API a little bit, but I don't know much about it and how it would relate to this.
Note that I've tried hint, but it is unsuitable for my application because it is not threadsafe.
Use the package hint
we can define eval
very easily, following is an example as self-contained script (you still need nix to run it)
#!/usr/bin/env nix-shell
#! nix-shell -p "haskellPackages.ghcWithPackages (p: with p; [hint])"
#! nix-shell -i "ghci -ignore-dot-ghci -fdefer-type-errors -XTypeApplications"
{-# LANGUAGE ScopedTypeVariables, TypeApplications, PartialTypeSignatures #-}
import Data.Typeable (Typeable)
import qualified Language.Haskell.Interpreter as Hint
-- DOC: https://www.stackage.org/lts-18.18/package/hint-0.9.0.4
eval :: forall t. Typeable t => String -> IO t
eval s = do
mr <- Hint.runInterpreter $ do
Hint.setImports ["Prelude"]
Hint.interpret s (Hint.as :: t)
case mr of
Left err -> error (show err)
Right r -> pure r
-- * Interpret expressions into values:
e1 = eval @Int "1 + 1 :: Int"
e2 = eval @String "\"hello eval\""
-- * Send values from your compiled program to your interpreted program by interpreting a function:
e3 = do
f <- eval @(Int -> [Int]) "\\x -> [1..x]"
pure (f 5)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With