Haskell 何谓“;用equals替换equals”;
我是Haskell新手,正在阅读: 它说“在哈斯克尔,一个人总是可以“用相等代替相等”,就像你们在代数课上学到的一样。”。这意味着什么?它的优点是什么Haskell 何谓“;用equals替换equals”;,haskell,Haskell,我是Haskell新手,正在阅读: 它说“在哈斯克尔,一个人总是可以“用相等代替相等”,就像你们在代数课上学到的一样。”。这意味着什么?它的优点是什么 我不记得在代数中学过这个,但也许我不认识这个术语。这意味着,如果你知道A(一个表达式)等于B(另一个表达式),那么在任何涉及A的表达式中,你都可以将A替换为B,反之亦然 例如,我们知道偶数=not。奇数。所以 filter even = filter (not . odd) 另一方面,我们知道,odd满足以下等式 odd =
我不记得在代数中学过这个,但也许我不认识这个术语。这意味着,如果你知道
A
(一个表达式)等于B
(另一个表达式),那么在任何涉及A
的表达式中,你都可以将A
替换为B
,反之亦然
例如,我们知道偶数=not。奇数
。所以
filter even
=
filter (not . odd)
另一方面,我们知道,odd
满足以下等式
odd = (1 ==) . (`mod` 2)
因此,我们也知道
filter even
=
filter (not . odd)
=
filter (not . (1 ==) . (`mod` 2))
此外,您知道mod 2
总是返回0
或1
。因此,通过案例分析,以下结论是有效的
not . (1 ==)
=
(0 ==)
所以我们也可以说
filter even
=
filter ((0 ==) . (`mod` 2))
用等号替换等号的好处是设计一个程序,通过一个接一个地处理方程,直到找到合适的定义,就像典型的求解x类代数问题一样。在最简单的形式中,“等号替换等号”意味着用定义替换定义的标识符。比如说
let x = f 1 in x + x
可以等价地写为
f 1 + f 1
从某种意义上说,结果是一样的。在GHC中,您可以预期第二个将重新计算f1
两次,这可能会降低性能,但求和的结果是相同的
在不纯正的语言中,例如Ocaml,上面的两个片段不是等价的。这是因为副作用是允许的:评估f1
会产生明显的影响。例如,f
可以定义如下:
(*Ocaml代码*)
设f=设r=参考0 in
乐趣x->r:=!r+x!R
使用上面的定义,f
有一个内部可变状态,在返回新状态之前,每次调用它时,它都会被它的参数递增。因此,
f 1 + f 1
将计算为1+2
,因为状态增加了两次,而
let x = f 1 in x + x
将计算为1+1
,因为只执行一次状态增量
其结果是,在Ocaml中,用其定义替换
x
将不是一种语义保留的程序转换。当然,在命令式语言中也是如此,这会产生副作用。只有在纯语言(Haskell、Agda、Coq等)中,转换才是安全的。这正是您所想的。如果表达式e1
等于表达式e2
,则可以在任何表达式中用e2
替换e1
。一个简单的例子可能是1+1
,它可以很容易地被2
,或者(\x.y)z
,在表达式(\x.x)(\x.y)z
中包含y