Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 何谓“;用equals替换equals”;_Haskell - Fatal编程技术网

Haskell 何谓“;用equals替换equals”;

Haskell 何谓“;用equals替换equals”;,haskell,Haskell,我是Haskell新手,正在阅读: 它说“在哈斯克尔,一个人总是可以“用相等代替相等”,就像你们在代数课上学到的一样。”。这意味着什么?它的优点是什么 我不记得在代数中学过这个,但也许我不认识这个术语。这意味着,如果你知道A(一个表达式)等于B(另一个表达式),那么在任何涉及A的表达式中,你都可以将A替换为B,反之亦然 例如,我们知道偶数=not。奇数。所以 filter even = filter (not . odd) 另一方面,我们知道,odd满足以下等式 odd =

我是Haskell新手,正在阅读:

它说“在哈斯克尔,一个人总是可以“用相等代替相等”,就像你们在代数课上学到的一样。”。这意味着什么?它的优点是什么


我不记得在代数中学过这个,但也许我不认识这个术语。

这意味着,如果你知道
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