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

Parsing “eval::String->(a->b)”字符串到函数转换器,parsing,haskell,functional-programming,eval,Parsing,Haskell,Functional Programming,Eval,Haskell标准库或其他一些模块/包中是否有一个函数可以接受字符串文本,如+,head等,然后将其转换为相应的Haskell函数,如+,head等 胡格尔没有给出任何立即有用的答案。此类函数的虚拟示例如下所示: eval :: String -> (a -> b) eval "+" = (+) eval "head" = head p、 考虑到此处的对应可能意味着不同上下文下的不同事物+可能不再被定义为非数字类型的数字加法,但这是回答此问题所必需的,让我们假设字符串的对应函数是类

Haskell标准库或其他一些模块/包中是否有一个函数可以接受字符串文本,如+,head等,然后将其转换为相应的Haskell函数,如+,head等

胡格尔没有给出任何立即有用的答案。此类函数的虚拟示例如下所示:

eval :: String -> (a -> b)
eval "+" = (+)
eval "head" = head
p、 考虑到此处的对应可能意味着不同上下文下的不同事物+可能不再被定义为非数字类型的数字加法,但这是回答此问题所必需的,让我们假设字符串的对应函数是类型检查的函数,可以在字符串转换为该函数的环境中进行计算,也称为。使用词法范围查找该函数的值

如果没有这样的函数,是否有深层次的原因,例如来自lambda演算、类型理论等。为什么?是否不可能在任何严格的静态类型语言中实现?如果这在Haskell中是不可能的,那么对于这样的问题,推荐的做法是什么?想象一下实现一个线性代数库,其中字符串要么求值为创建值的函数,例如vect2是创建二维函数的函数,要么是二进制函数,为了简单起见,可以将字符串映射到其他类型,我们可以选择为这些字符串提供类型注释,例如求值innerProduct::Double,评估矩阵产品::矩阵等


更一般地说,字符串类型具有种类*,而函数->具有种类*->*->*->*。假设我们可以从词汇范围提供前两种,这应该是可能的,对吗

不,没有这样的功能。

不,没有这样的功能。

如果我有一个功能

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
然而,这种存在类型的值对于其他任何东西都是不可用的。给定一个有趣的字符串,你不能将函数应用于字符串,因为函数可能需要一个布尔输入,就我们所知

一个更明智的选择是使用Typeable

如果字符串没有针对所选的a和b进行类型检查,而解析字符串并将其计算为正确类型的函数,则此操作可能不会返回任何结果

顺便问一下,为什么这种评估的结果应该限制在一个函数中?这样做似乎毫无意义

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

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

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

TL;博士,对于任何不严格要求评估的东西,使用评估可能是一个非常糟糕的主意。避免它。

如果我有一个函数

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
然而,这种存在类型的值对于其他任何东西都是不可用的。给定一个有趣的字符串,你不能将函数应用于字符串,因为函数可能需要一个布尔输入,就我们所知

一个更明智的选择是使用Typeable

如果字符串没有针对所选的a和b进行类型检查,而解析字符串并将其计算为正确类型的函数,则此操作可能不会返回任何结果

顺便问一下,为什么这种评估的结果应该限制在一个函数中?这样做似乎毫无意义

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

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

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

TL;博士,对于任何不严格要求评估的东西,使用评估可能是一个非常糟糕的主意。避免使用它。

相关:你可能喜欢,它可以让你反向控制:你的程序不是把一个字符串作为Haskell来计算,而是编写一些Haskell来使用libra中公开的东西
ry和dyre在字符串更改时处理移交给GHC的任务。当然也有GHC API和建立在它们之上的东西,比如和。相关的:你可能喜欢,这让你可以反转控制:你的程序不是把一个字符串作为Haskell来计算,而是编写一些Haskell,它使用你库中公开的东西,dyre处理字符串变化时交给GHC的工作。当然也有GHC API和建立在它们之上的东西,如and。问题编辑了更多关于上下文和通信的信息。@hyiltiz:嗯,有这样一个函数。它被称为编译器@泽塔:编译器可以/将要做其中的一部分。然而,在Haskell的例子中,它也懒散地计算函数。我还没有要求对函数求值,只是将字符串转换为函数。@hyiltiz不,编译器通常不会运行它生成的程序。是什么让你说编译器也会计算函数?@hylitiz编译器不会“计算函数”。惰性计算是通过thunks完成的,当然不是由编译器在运行时完成的。Haskell不是一种脚本语言,因此不存在这样的函数。编辑问题时,请提供有关上下文和对应关系的详细信息。@hyiltiz:嗯,有这样一个函数。它被称为编译器@泽塔:编译器可以/将要做其中的一部分。然而,在Haskell的例子中,它也懒散地计算函数。我还没有要求对函数求值,只是将字符串转换为函数。@hyiltiz不,编译器通常不会运行它生成的程序。是什么让你说编译器也会计算函数?@hylitiz编译器不会“计算函数”。惰性计算是通过thunks完成的,当然不是由编译器在运行时完成的。Haskell不是脚本语言,所以不存在这样的函数。如果可以在没有IO包装器和GHC覆盖信号处理程序的情况下编写eval::Typeable a=>String->也许a,那就太好了。我认为这是eval之类的事情的唯一副作用。@Cirdec您能详细介绍一下IO包装器和GHC覆盖信号处理程序吗?似乎很有趣。@chi我知道使用eval实际计算随机字符串是一个非常糟糕的主意,但不确定为什么将字符串转换为值/函数是一个糟糕的主意。@hyiltiz将字符串转换为我们读过的一阶值。对于函数,这取决于您想要实现什么。如果你正在写一个口译员,那没关系。比如说,如果字符串只能是*和+,那么使用eval就太过分了,而且有潜在的危险。同样,正如我在上面写的,为什么要绕过静态类型系统呢?我用静态类型语言编程来早期检测错误,eval将编译时错误转化为运行时错误,这对我来说是非常糟糕的——Haskell的整个理念都是相反的way@Cirdec它还需要您的运行时包含GHC编译器的副本!例如,hint中存在的IO约束是因为它通过系统命令启动GHC进程的副本,并通过管道与新进程交互。如果能够在没有IO包装器和GHC覆盖信号处理程序的情况下编写eval::Typeable a=>String->Maybe a(我认为这是唯一的副作用),那就太好了您能详细介绍一下IO包装器和GHC覆盖信号处理程序吗?似乎很有趣。@chi我知道使用eval实际计算随机字符串是一个非常糟糕的主意,但不确定为什么将字符串转换为值/函数是一个糟糕的主意。@hyiltiz将字符串转换为我们读过的一阶值。对于函数,这取决于您想要实现什么。如果你正在写一个口译员,那没关系。比如说,如果字符串只能是*和+,那么使用eval就太过分了,而且有潜在的危险。同样,正如我在上面写的,为什么要绕过静态类型系统呢?我用静态类型语言编程来早期检测错误,eval将编译时错误转化为运行时错误,这对我来说是非常糟糕的——Haskell的整个理念都是相反的way@Cirdec它还需要您的运行时包含GHC编译器的副本!例如提示中存在的IO约束是因为它通过系统命令启动GHC流程的副本,并通过管道与新流程交互。