[英]Functional Purity using 'let' in Haskell
As I am working on learning Haskell, I understand it is a purely functional language. 在学习Haskell的过程中,我了解它是一种纯粹的功能语言。 I am having trouble understanding why
let
-statements don't violate purity. 我很难理解为什么
let
陈述不会违反纯洁。
For example (in ghci): 例如(在ghci中):
Prelude> let e = exp 1
Prelude> e
2.718281828459045
Prelude> let e = 2
Prelude> e
2
isn't my second let
statement producing a side effect? 我的第二个
let
语句不会产生副作用吗? Or is the second let
statement a new closure? 还是第二个
let
语句重新闭合?
Your second let
creates a new binding for e
that shadows the existing variable. 第二个
let
为e
创建一个新的绑定,该绑定遮盖了现有变量。 It does not modify e
. 它不会修改
e
。 You can easily check this with the following: 您可以使用以下方法轻松检查:
Prelude> let e = 1
Prelude> let f () = "e is now " ++ show e
Prelude> f ()
"e is now 1"
Prelude> let e = 2
Prelude> e
2
Prelude> f ()
"e is now 1"
Prelude>
let
introduces a new local variable with a single unalterable value, and it has more local scope than any surrounding definitions, so for example: let
引入一个具有单个不可更改值的新局部变量,它的局部作用域比周围的任何定义都多,因此例如:
*Main> (let length = 2 in show length) ++ ' ':show (length "Hello")
"2 5"
Here the first length
has the value 2, but its scope local to the brackets. 在这里,第一个
length
的值是2,但范围仅限于方括号。 Outside the brackets, length
means what it has always meant. 在括号之外,
length
表示它一直以来的含义。 Nothing has been edited, just a more local variable has been introduced that happens to have the same name as another one in a different scope. 没有进行任何编辑,只引入了一个更多的局部变量,该变量恰好与另一个作用域的名称相同。 Let's make ghci mad by omitting the brackets and making it try to make
length
a number and a function: 让我们让ghci疯狂,省去括号并尝试使
length
成为数字和函数:
*Main> let length = 2 in show length ++ ' ':show (length "Hello")
<interactive>:1:14:
No instance for (Num ([Char] -> a0))
arising from the literal `2'
Possible fix: add an instance declaration for (Num ([Char] -> a0))
In the expression: 2
In an equation for `length': length = 2
In the expression:
let length = 2 in show length ++ ' ' : show (length "Hello")
<interactive>:1:19:
No instance for (Show ([Char] -> a0))
arising from a use of `show'
Possible fix: add an instance declaration for (Show ([Char] -> a0))
In the first argument of `(++)', namely `show length'
In the expression: show length ++ ' ' : show (length "Hello")
In the expression:
let length = 2 in show length ++ ' ' : show (length "Hello")
And here's your example: 这是您的示例:
*Main> let e = exp 1 in show e ++ " " ++ let e = 2 in show e
"2.718281828459045 2"
I'll add brackets to emphasise the scope: 我将添加方括号以强调范围:
*Main> let e = exp 1 in (show e ++ " " ++ (let e = 2 in (show e)))
"2.718281828459045 2"
The first e
is hidden rather than edited. 第一个
e
被隐藏而不是被编辑。 Referential transparency is preserved, but it's definitely bad practice because it's hard to follow. 参照透明性得到保留,但是绝对不明智,因为它很难遵循。
Now secretly the interactive prompt is a bit like one big do
block in the IO monad, so let's look at that: 现在,秘密地,交互式提示有点像IO monad中的一个大
do
块,所以让我们看一下:
testdo = do
let e = exp 1
print e
let e = 2
print e
Now I have to admit that looks an awful lot like breaking referential transparency, but bear in mind that this looks like it does too: 现在,我不得不承认,这看起来很像破坏参照透明性,但请记住,这看起来也确实如此:
testWrite = do
writeFile "test.txt" "Hello Mum"
xs <- readFile "test.txt"
print xs
writeFile "test.txt" "Yo all"
xs <- readFile "test.txt"
print xs
Now in what sense have we got referential transparency? 现在,在什么意义上我们已经获得了参照透明性?
xs
clearly refers to two different strings. xs
显然是指两个不同的字符串。 Well, what does this do
notation actually mean? 那么,这是什么
do
记号实际上意味着什么呢? It's syntactic sugar for 这是语法糖
testWrite = writeFile "test.txt" "Hello Mum"
>> readFile "test.txt"
>>= (\xs -> print xs
>> writeFile "test.txt" "Yo all"
>> readFile "test.txt"
>>= (\xs -> print xs))
Now it's clearer that what looks like assignment is just local scope again. 现在,更清楚的是分配看起来又只是局部作用域。 You presumably are happy to do
您大概很高兴做
increment :: [Int] -> [Int]
increment = \x -> map (\x -> x+1) x
Which is doing the same thing. 哪个在做同样的事情。
Summary 摘要
What appeared to be assignment is just introduction of a new local scope. 似乎只是分配了一个新的本地范围。 Phew.
ew If you use this a lot, you make it very unclear what your code means.
如果您经常使用此功能,则会很不清楚代码的含义。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.