假设我有这个功能:
squared x = x ** 2
Run Code Online (Sandbox Code Playgroud)
我想从控制台读取它并应用它。可以做这样的事情吗:
gchi> (read("squared) :: Int -> Int) 4
Run Code Online (Sandbox Code Playgroud)
没有; 通常,这是不可能的。要了解原因,请考虑存在此功能时可能发生的几种情况:
(+) a b = a - b。现在,应该read "(+)"是(+)Prelude中的还是重新定义的(+)运算符?read "foobar",foobar但尚未将其定义为函数,那么应该返回什么?然后,如果foobar在模块中的其他位置定义了该命令,import Prelude ()程序添加到程序的顶部(从Prelude中删除所有导入),应该read "preludeFunctionName"停止工作吗?现在,这些问题本身都不是破坏交易的因素-用另一种语言,您仍然可以定义一个read考虑这些问题的函数。在这种情况下,问题是参照透明性:IO给定相同的输入,非函数应始终返回相同的输出的属性。由于的类型read是Read a => String -> a,而不是Read a => String -> IO a,因此您无法根据需要创建一个实例read,因为上述函数可以根据运行它的确切上下文给出不同的答案。(例如read "foobar"和let foobar = (+1) in read "foobar"将对同一函数调用给出不同的答案。)
另一方面,如果您仍想拥有此功能,则有一种获取它的方法。该hint程序包允许在运行时解释Haskell代码,因此您可以使用此功能编写如下函数:
-- Warning: the following code is untested
-- Please comment if you find any errors!
import Language.Haskell.Interpreter
readFn :: Typeable a
=> [ModuleName] -- ^ Modules to search
-> String -- ^ Function to read
-> a -- ^ Witness for the type a
-> IO (Either InterpreterError a)
readFn m f w = runInterpreter $ do
setImports m
interpret f w
Run Code Online (Sandbox Code Playgroud)
上面的功能可以如下使用:
readFn ["Prelude"] "(+)" (as :: Num a => a -> a -> a)
Run Code Online (Sandbox Code Playgroud)
哪里as是Language.Haskell.Interpreter。
| 归档时间: |
|
| 查看次数: |
68 次 |
| 最近记录: |