'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" 在不同的上下文中可能意味着不同的东西(+
可能不再被定义为非 Num
bers 类型的数字加法)但是有必要回答这个问题,让我们假设字符串的 "corresponding" 函数是类型检查的函数,并且可以在将字符串转换为此函数 a.k.a 的环境中进行评估。使用词法范围查找此函数的值。
如果没有这样的函数,是否有更深层的原因(例如来自 lambda 演算、类型理论等),以及是否不可能在任何严格的静态类型语言中实现?如果在 Haskell 中不可能,对于此类问题,实际上推荐的做法是什么?想象一下实现一个线性代数库,其中字符串要么评估为创建值的函数(例如 vect2
是一个创建二维函数的函数),要么(二进制, 为简单起见[=39=])从它们映射到其他类型的操作(我们可以选择为这些操作提供类型注释,例如 eval "innerProduct" :: Double
、eval "matrixProduct" :: Matrix
等)
更一般地说,String
类型有一个种类 *
,但是函数 ->
有一个种类 * -> * -> *
。假设我们可以从词法作用域提供前两种*
,应该可以吧?
没有,没有这个功能
如果我有函数
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)
当字符串未针对所选 a
和 b
进行类型检查时,这可能 return Nothing
,同时解析字符串并将其评估为函数否则是正确的类型。
(顺便说一句,为什么这样的eval
的结果要限制在一个函数中?这样做似乎没有意义。)
这在原则上是可以实现的。这些库实际上包含 System.Eval.Haskell.eval
以达到类似的目的。
但是,除非你真的想编写一个在运行时接收 Haskell 代码并解释它的程序,否则我强烈建议你避免像 eval
这样的东西。将它用于普通编程似乎严重违反了该语言的精神及其习语,并且可能规避类型系统提供的静态保证,将编译时错误转化为运行时错误。
虽然我不是专家,但我认为在脚本语言中使用 eval
通常被认为是一个非常糟糕的设计。
长话短说;博士。对于任何不严格要求 eval
的东西,使用 eval
可能是一个非常糟糕的主意。避开它。
Haskell 标准库(或其他一些模块/包)中是否有函数可以使用 String
文字,例如 "+"
、"head"
等。 ,然后将它们转换为它们的 对应的 Haskell 函数,例如 +
、head
?
Hoogle 没有产生任何立即有用的答案。这种函数的虚拟示例将像这样工作:
eval :: String -> (a -> b)
eval "+" = (+)
eval "head" = head
p.s。鉴于这里的 "corresponding" 在不同的上下文中可能意味着不同的东西(+
可能不再被定义为非 Num
bers 类型的数字加法)但是有必要回答这个问题,让我们假设字符串的 "corresponding" 函数是类型检查的函数,并且可以在将字符串转换为此函数 a.k.a 的环境中进行评估。使用词法范围查找此函数的值。
如果没有这样的函数,是否有更深层的原因(例如来自 lambda 演算、类型理论等),以及是否不可能在任何严格的静态类型语言中实现?如果在 Haskell 中不可能,对于此类问题,实际上推荐的做法是什么?想象一下实现一个线性代数库,其中字符串要么评估为创建值的函数(例如 vect2
是一个创建二维函数的函数),要么(二进制, 为简单起见[=39=])从它们映射到其他类型的操作(我们可以选择为这些操作提供类型注释,例如 eval "innerProduct" :: Double
、eval "matrixProduct" :: Matrix
等)
更一般地说,String
类型有一个种类 *
,但是函数 ->
有一个种类 * -> * -> *
。假设我们可以从词法作用域提供前两种*
,应该可以吧?
没有,没有这个功能
如果我有函数
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)
当字符串未针对所选 a
和 b
进行类型检查时,这可能 return Nothing
,同时解析字符串并将其评估为函数否则是正确的类型。
(顺便说一句,为什么这样的eval
的结果要限制在一个函数中?这样做似乎没有意义。)
这在原则上是可以实现的。这些库实际上包含 System.Eval.Haskell.eval
以达到类似的目的。
但是,除非你真的想编写一个在运行时接收 Haskell 代码并解释它的程序,否则我强烈建议你避免像 eval
这样的东西。将它用于普通编程似乎严重违反了该语言的精神及其习语,并且可能规避类型系统提供的静态保证,将编译时错误转化为运行时错误。
虽然我不是专家,但我认为在脚本语言中使用 eval
通常被认为是一个非常糟糕的设计。
长话短说;博士。对于任何不严格要求 eval
的东西,使用 eval
可能是一个非常糟糕的主意。避开它。