新用户,半noobie Haskell程序员在这里。我一直在寻找并在48小时内为自己写一个方案'我突然意识到,尽管在实践中它会非常不安全,但看看Haskell程序是否可以阅读'一个功能。
例如,read "+" :: Num a => a -> a -> a
- (即(+)的类型)
然而,上面的例子不起作用。有任何想法吗?我知道在实践中这是一个非常愚蠢的事情,但如果有可能的话会很酷,对吗?
答案 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
包得到的那样)那么你可以做你想要的。