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