hyi*_*tiz 1 parsing haskell functional-programming eval
有在Haskell标准库中的函数(或一些其他模块/包),可以采取一个String字面如"+","head"等等,然后把这些成其相应的Haskell功能,诸如+,head?
Hoogle没有产生任何立即有用的答案.这样一个函数的虚拟示例将如下所示:
eval :: String -> (a -> b)
eval "+" = (+)
eval "head" = head
Run Code Online (Sandbox Code Playgroud)
ps假设这里的"对应"可以表示不同上下文中的不同事物(+可能不再被定义为非Numbers 类型的数字加法)但是回答这个问题是必要的,让我们假设字符串的"对应"函数是类型检查的函数,可以在将字符串转换为此函数的环境中进行求值,也就是使用词法作用域来查找此函数的值.
如果没有这样的功能,是否有深层原因(例如来自lambda演算,类型理论等)为什么,并且不可能在任何严格的静态类型语言中实现?如果在Haskell中不可能,对于这样的问题,实际上建议的做法是什么?想象一下,实现一个线性代数库,其中字符串或者eval到创建值vect2的函数(例如,是一个创建二维函数的函数),或者(二进制,为了简单)操作,从它们映射到其他类型(我们可以选择提供类型)这些注释,例如eval "innerProduct" :: Double,eval "matrixProduct" :: Matrix等)
更一般地说,一种String类型有一种*,但一种功能->有一种* -> * -> *.假设我们可以*从词法范围中提供前两种,那么应该是可能的,对吧?
如果我有一个功能
eval :: String -> (a -> b)
Run Code Online (Sandbox Code Playgroud)
然后,以下代码类型检查:
foo :: Int -> Int -> Int
foo = eval "(+)"
bar :: Char -> Bool
bar = eval "(+)"
Run Code Online (Sandbox Code Playgroud)
显然有些不对劲.你想要的,首先是量化a和 b 存在而不是普遍的.
data Fun where
Fun :: (a -> b) -> Fun
eval :: String -> Fun
Run Code Online (Sandbox Code Playgroud)
但是,这种存在类型的值将无法用于其他任何事物.给定一个Fun和一个字符串,你不能将该函数应用于字符串,因为该函数可能需要一个布尔输入,我们知道.
一个更明智的选择可能是使用Typeable.
eval :: (Typeable a, Typeable b) => String -> Maybe (a -> b)
Run Code Online (Sandbox Code Playgroud)
Nothing当字符串没有针对所选字符串进行类型检查时,这可能会返回,a并且b在解析字符串并将其评估为正确类型的函数时也会返回.
(顺便说一下,为什么这样的结果eval应该被约束到一个函数?这样做似乎没有意义.)
原则上,这是可以实现的.实际上,图书馆包含System.Eval.Haskell.eval了类似的目标.
但是,除非你真的想编写一个在运行时接收Haskell代码并解释它的程序,否则我强烈建议你避免使用类似的东西eval.将它用于普通编程似乎严重违反了语言的精神,它的习语,并且可能绕过类型系统提供的静态保证,将编译时错误转化为运行时.
虽然我不是专家,但我认为eval在脚本语言中使用通常被认为是一个非常糟糕的设计.
TL; DR.eval用于任何不严格要求的东西可能是一个非常糟糕的主意eval.躲开它.