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

'eval :: String -> (a -> b)' string to function converter

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

Hoogle 没有产生任何立即有用的答案。这种函数的虚拟示例将像这样工作:

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

p.s。鉴于这里的 "corresponding" 在不同的上下文中可能意味着不同的东西(+ 可能不再被定义为非 Numbers 类型的数字加法)但是有必要回答这个问题,让我们假设字符串的 "corresponding" 函数是类型检查的函数,并且可以在将字符串转换为此函数 a.k.a 的环境中进行评估。使用词法范围查找此函数的值。

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

更一般地说,String 类型有一个种类 *,但是函数 -> 有一个种类 * -> * -> *。假设我们可以从词法作用域提供前两种*,应该可以吧?

没有,没有这个功能

如果我有函数

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)

当字符串未针对所选 ab 进行类型检查时,这可能 return Nothing,同时解析字符串并将其评估为函数否则是正确的类型。

(顺便说一句,为什么这样的eval的结果要限制在一个函数中?这样做似乎没有意义。)

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

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

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

长话短说;博士。对于任何不严格要求 eval 的东西,使用 eval 可能是一个非常糟糕的主意。避开它。