Haskell 纯函数可以有自由变量吗?

Haskell 纯函数可以有自由变量吗?,haskell,functional-programming,pure-function,free-variable,Haskell,Functional Programming,Pure Function,Free Variable,例如,没有自由变量的引用透明函数: g op x y = x `op` y A现在是一个具有自由变量的函数(从f的角度来看)op和x: x = 1 op = (+) f y = x `op` y f在引用上也是透明的。但这是一个纯函数吗 如果它不是一个纯函数,那么一个引用透明但使用了一个或多个绑定在封闭范围内的变量的函数的名称是什么 提出这个问题的动机: 我不清楚这篇文章: 结果值不需要依赖于所有(或任何)参数值但是,它只能依赖于参数值。 (强调矿山) 也不是从搜索纯函数是否可以依赖于fr

例如,没有自由变量的引用透明函数:

g op x y = x `op` y
A现在是一个具有自由变量的函数(从
f
的角度来看)
op
x

x = 1
op = (+)
f y = x `op` y
f
在引用上也是透明的。但这是一个纯函数吗

如果它不是一个纯函数,那么一个引用透明但使用了一个或多个绑定在封闭范围内的变量的函数的名称是什么


提出这个问题的动机:

我不清楚这篇文章:

结果值不需要依赖于所有(或任何)参数值但是,它只能依赖于参数值。

(强调矿山)

也不是从搜索纯函数是否可以依赖于free(即绑定在封闭范围内,而不是绑定在函数范围内)变量

还有,他说:

如果没有自由变量的函数是纯函数,闭包是纯函数吗

函数
函数(y){return x}
很有趣。它包含一个 自由变量x。自由变量是指不受约束的变量 功能。到目前为止,我们只看到了一种“绑定”变量的方法, 也就是说,传入一个同名的参数。自从 函数
函数(y){return x}
没有名为x的参数, 变量x未绑定在此函数中,这使其“自由”

现在我们知道函数中使用的变量是有界的或有界的 free,我们可以将函数分成具有自由变量和 没有:

  • 不包含自由变量的函数称为纯函数。
  • 包含一个或多个自由变量的函数称为闭包。

那么“纯函数”的定义是什么呢?据我所知,“纯函数”是在语义层面上定义的,而“引用透明函数”可以在语法上具有意义,也可以嵌入到lambda演算替换规则中。定义其中任何一个都会带来一点挑战,因为我们需要有一个强有力的项目平等概念,这可能是一个挑战。最后,需要注意的是,自由变量的概念完全是语法的,一旦你进入了一个值域,你就不能再有带有自由变量的表达式了,它们必须被绑定,否则就是语法错误

但让我们深入研究,看看这是否变得更清楚


奎宁参照透明度 我们可以非常广泛地将引用透明性定义为语法上下文的属性。根据最初的定义,这将由以下句子构成

New York is an American city.
我们已经挖了一个洞

_ is an American city.
这样一个空洞的句子,一个“上下文”,被认为是指代透明的,如果给定两个句子片段都“指”同一事物,用这两个片段中的任何一个填充上下文都不会改变其含义

要明确的是,我们可以选择的两个具有相同引用的片段将是“纽约”和“大苹果”。注入我们写的那些片段

New York is an American city.
The Big Apple is an American city.
暗示

_ is an American city.
在引用上是透明的。为了演示典型的反例,我们可以写

"The Big Apple" is an apple-themed epithet referring to New York.

并考虑上下文

"_" is an apple-themed epithet referring to New York.
现在当我们注入两个相同的短语时,我们得到一个有效和一个无效的句子

"The Big Apple" is an apple-themed epithet referring to New York.
"New York" is an apple-themed epithet referring to New York.
换句话说,引用破坏了引用的透明度。我们可以通过使句子引用一个句法结构而不是纯粹的该结构的意义来了解这是如何发生的。这一概念将在稍后出现


语法与语义 有一点令人困惑,上面提到的参照透明度的定义直接适用于英语句子,我们通过逐字逐句地删除单词来构建上下文。虽然我们可以用编程语言做这件事,并考虑这样的上下文是否是透明的,我们也可以认识到这种“替代”的想法对计算机语言的概念是至关重要的。 因此,我们要明确的是,我们可以考虑两种参考透明性:λ演算句法和语义两种。句法方面的要求是我们将“上下文”定义为用编程语言编写的文字中的漏洞。这让我们考虑了像

这样的漏洞。
let x = 3 in _
然后用“x”之类的词填充。我们将把替换的分析留待以后进行。在语义层面,我们使用lambda术语来表示上下文

\x -> x + 3         --    similar to the context "_ + 3"
和仅限于用有效的语义值(由应用程序执行)而不是语法片段来填补漏洞

(\x -> x + 3) 5 
==> 
5 + 3
==> 
8
所以,当有人在Haskell中提到引用透明性时,弄清楚他们所指的是什么类型的引用透明性是很重要的


这个问题指的是哪一种?因为它是关于一个包含自由变量的表达式的概念,我建议它是语法的。我在这里的推理主要有两个要点。首先,为了将语法转换为语义,需要语法有效。在Haskell的例子中,这意味着语法有效性和成功的类型检查。然而,我们会注意到一个程序片段

x + 3
实际上是一个语法错误,因为<代码> x <代码>是完全未知的,未绑定的,使我们无法把它的语义看作Haskell程序。第二,一个变量的概念,例如一个可以是<代码>让 IORef <代码> >)完全是一个句法结构。 因此,让我们将问题细化为:

包含自由变量的表达式是否可以(语法上)引用
E1 ... x ... _ ... E2
E1 ... x ... let x = 3 in E ... E2
do x <- foo
   let x = 3
   _
   return x
let x = 3 in _
let x = 3 in x   ==/==  let x = 3 in y
foo >>= \x -> (let x = 3 in ____(return x)_____)
trivial :: a -> ()
trivial x = x `seq` ()
trivial_Int :: Int -> ()
trivial_Int x = x `seq` ()
trivial_b . f = trivial_a
increment n = 1+n
add x = (\y -> x+y)