'eval :: String - > (a - > b)'字符串到函数转换器

时间:2017-04-14 18:35:56

标签: parsing haskell functional-programming eval

Haskell标准库(或其他一些模块/包)中是否有一个函数可以使用String文字,例如"+""head"等,然后将它们转换为它们的相应的 Haskell函数,例如+head

Hoogle没有立即提供有用的答案。这样一个函数的一个假例子就是这样的:

eval :: String -> (a -> b)
eval "+" = (+)
eval "head" = head

P.S。鉴于此处的“对应”可能意味着在不同的上下文中不同的事物(+可能不再被定义为不是Num bers的类型的数字加法)但是必须回答这个问题,让我们假设字符串的“对应”函数是类型检查的函数,可以在将字符串转换为此函数的环境中进行求值,也就是使用词法作用域来查找此函数的值。

如果没有这样的功能,是否存在深层原因(例如来自lambda演算,类型理论等)为什么,并且是否无法在任何严格的静态类型语言中实现?如果在Haskell中不可能,对于这样的问题,实际上建议的做法是什么?想象一下,实现一个线性代数库,其中字符串eval到创建值的函数(例如vect2是一个创建二维函数的函数),或者(二进制,为简单起见)操作映射从它们到其他类型(我们可以选择为这些类型提供类型注释,例如eval "innerProduct" :: Doubleeval "matrixProduct" :: Matrix等。)

更一般地说,String类型有一种*,但函数->有一种* -> * -> *。假设我们可以从词法范围中提供前两种*,它应该是可能的,对吗?

2 个答案:

答案 0 :(得分:7)

如果我有一个功能

eval :: String -> (a -> b)

然后,以下代码类型检查:

foo :: Int -> Int -> Int
foo = eval "(+)"

bar :: Char -> Bool
bar = eval "(+)"

显然有些不对劲。您想要开始的是量化ab 存在而非普遍。

data Fun where
   Fun :: (a -> b) -> Fun

eval :: String -> Fun

但是,这种存在类型的值将无法用于其他任何事情。给定一个Fun,比如一个字符串,你不能将该函数应用于字符串,因为该函数可能需要一个布尔输入,我们知道。

更明智的选择可能是使用Typeable

eval :: (Typeable a, Typeable b) => String -> Maybe (a -> b)

当字符串未针对所选的Nothinga进行类型检查时,这可能会返回b,同时解析字符串并将其评估为正确类型的函数。 / p>

(顺便说一下,为什么这样的eval的结果应该被约束到一个函数?这样做似乎没有意义。)

原则上,这是可以实现的。实际上,这些库包含System.Eval.Haskell.eval以达到类似的目的。

但是,除非您真的想编写一个在运行时接收Haskell代码并解释它的程序,否则我强烈建议您避免使用eval之类的内容。将它用于普通编程似乎严重违反了语言的精神,习惯用语,并且可能绕过类型系统提供的静态保证,将编译时错误转化为运行时。

虽然我不是专家,但我认为在脚本语言中使用eval通常被认为是一种非常糟糕的设计。

TL; DR。将eval用于不严格要求eval的任何内容可能是一个非常糟糕的主意。避免它。

答案 1 :(得分:4)

不,没有这样的功能。