是否有可能在Haskell中“读取”一个函数?

时间:2014-06-03 23:07:55

标签: haskell

新用户,半noobie Haskell程序员在这里。我一直在寻找并在48小时内为自己写一个方案'我突然意识到,尽管在实践中它会非常不安全,但看看Haskell程序是否可以阅读'一个功能。

例如,read "+" :: Num a => a -> a -> a - (即(+)的类型)

然而,上面的例子不起作用。有任何想法吗?我知道在实践中这是一个非常愚蠢的事情,但如果有可能的话会很酷,对吗?

2 个答案:

答案 0 :(得分:11)

Haskell是一种静态编译语言,您可以使用Language.Haskell.Interpreter将字符串解释为函数。

读取类型为Int -> Int -> Int的二进制函数的最小示例是:

import Language.Haskell.Interpreter
import System.Environment (getArgs)

main :: IO ()
main = do
  args <- getArgs
  -- check that head args exists!
  errorOrF <- runInterpreter $ do
    setImports ["Prelude"]
    interpret (head args) (as::Int -> Int -> Int)
  case errorOrF of
    Left errs -> print errs
    Right f   -> print $ f 1 2

您可以通过这种方式调用此程序(此处我假设代码为test.hs的文件名):

> ghc test.hs
...
> ./test "\\x y -> x + y"
3

程序的核心是runInterpreter,这是解释器解释String的地方。我们首先将Prelude模块添加到具有setImports的上下文中,以使其可用,例如+函数。然后我们调用interpret将第一个参数解释为函数,我们使用as Int -> Int -> Int来强制执行该类型。 runInterpreter的结果是Either InterpretError a,其中a是您的类型。如果结果是Left,则表示您有错误,否则您有自己的功能或价值。从Right中提取后,可以在使用Haskell函数时使用它。例如,请参阅上面的f 1 2

如果你想要一个更完整的例子,你可以检查haskell-awk,这是我的和gelisam项目,以实现一个类似awk的命令行实用程序,它使用Haskell代码而不是AWK代码。我们使用Language.Haskell.Interpreter来解释用户功能。

答案 1 :(得分:2)

一般的答案是,不,你不能。函数在Haskell中非常“不透明” - 你可以分析它们的唯一方法是对它们应用参数(或者使用类型类来从类型中提取信息,但这是不同的。)

这意味着以任何一种专门或简化的方式创建动态函数非常困难。您可以做的最好的事情是将解析器,解释器和序列化/反序列化机制嵌入到另一种语言中,然后解析该语言的字符串并在解释器中执行它们。

当然,如果你的解释语言只是Haskell(比如你使用hint包得到的那样)那么你可以做你想要的。