Language.Haskell.Interpreter:这是适合手头工作的正确工具吗?

时间:2016-09-27 00:47:00

标签: haskell eval interpreter

我对自然语言有一个小玩具语义,用以下单词:

ran :: String -> Bool
ran = (`elem` ["Bart", "Homer", "Marge"])

bart :: String
bart = "Bart"

例如,我可以拥有(ran bart) :: Bool,依此类推。

我想编写一个解析器,例如获取字符串"Bart ran"并返回True。我可能会使用Parsec。

然而,问题是能够通过字符串调用函数。例如。从"ran"转到函数ran。为此,我认为Language.Haskell.Interpreterinterpret功能可能是合适的。

所以我的问题是:

  1. 这是一种明智的方式来做我想做的事吗?

  2. 如果是,为什
    Grammar.hs

    我收到错误:

    ran

    这表明导入不起作用,事实上,如果我尝试使用Prelude函数进行类似的操作,一切都会正常工作。

    1. 如果我尝试编译与Q2中相同的代码(减去let a = runInterpreter $ do loadModules ["Grammar"] setImports ["Prelude"] interpret "ran" (as :: String -> Bool) let b = do x <- a return $ x <*> pure "John" b ),为什么会出现以下类型错误(以及许多其他错误):
    2.   

      使用"Left (WontCompile [GhcError {errMsg = "<interactive>:2:1:\n Not in scope: \8216ran\8217\n Perhaps you meant \8216tan\8217 (imported from Prelude)"}])"

      时,let没有任何实例

1 个答案:

答案 0 :(得分:2)

对于#2,您还需要将"Grammar"添加到setImports列表中:

runInterpreter $ do
    loadModules ["HintDefs"]
    setImports ["Prelude", "HintDefs"]
    interpret "ran" (as :: String -> Bool)

至于#3,这是因为runInterpreter在选择monad时是单态的:

runInterpreter :: (MonadIO m, MonadMask m) 
               => InterpreterT m a 
               -> m (Either InterpreterError a)

因此,您需要通过在例如{...}中运行来选择特定的mIO

main :: IO ()
main = do
    ran <- runInterpreter $ do
        loadModules ["HintDefs"]
        setImports ["Prelude", "HintDefs"]
        interpret "ran" (as :: String -> Bool)
    print $ ran <*> pure "John"

现在,至于#1,我不相信你需要像HInt这样愚蠢的强大功能。您可以维护一个由String -> Bool键加密的String函数字典,类似于Map String (String -> Bool),然后用它来查找ran等。