簡體   English   中英

在Haskell中使用“ let”的功能純度

[英]Functional Purity using 'let' in Haskell

在學習Haskell的過程中,我了解它是一種純粹的功能語言。 我很難理解為什么let陳述不會違反純潔。

例如(在ghci中):

Prelude> let e = exp 1
Prelude> e
2.718281828459045
Prelude> let e = 2
Prelude> e
2

我的第二個let語句不會產生副作用嗎? 還是第二個let語句重新閉合?

第二個lete創建一個新的綁定,該綁定遮蓋了現有變量。 它不會修改e 您可以使用以下方法輕松檢查:

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引入一個具有單個不可更改值的新局部變量,它的局部作用域比周圍的任何定義都多,因此例如:

*Main> (let length = 2 in show length) ++ ' ':show (length "Hello")
"2 5"

在這里,第一個length的值是2,但范圍僅限於方括號。 在括號之外, length表示它一直以來的含義。 沒有進行任何編輯,只引入了一個更多的局部變量,該變量恰好與另一個作​​用域的名稱相同。 讓我們讓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")

這是您的示例:

*Main> let e = exp 1 in show e ++ " " ++ let e = 2 in show e
"2.718281828459045 2"

我將添加方括號以強調范圍:

*Main> let e = exp 1 in (show e ++ " " ++ (let e = 2 in (show e)))
"2.718281828459045 2"

第一個e被隱藏而不是被編輯。 參照透明性得到保留,但是絕對不明智,因為它很難遵循。


現在,秘密地,交互式提示有點像IO monad中的一個大do塊,所以讓我們看一下:

testdo = do
  let e = exp 1
  print e
  let e = 2
  print e

現在,我不得不承認,這看起來很像破壞參照透明性,但請記住,這看起來也確實如此:

testWrite = do
   writeFile "test.txt" "Hello Mum"
   xs <- readFile "test.txt"
   print xs
   writeFile "test.txt" "Yo all"
   xs <- readFile "test.txt"
   print xs

現在,在什么意義上我們已經獲得了參照透明性? xs顯然是指兩個不同的字符串。 那么,這是什么do記號實際上意味着什么呢? 這是語法糖

testWrite = writeFile "test.txt" "Hello Mum"
         >> readFile "test.txt" 
         >>= (\xs -> print xs 
         >> writeFile "test.txt" "Yo all"
         >> readFile "test.txt"
         >>= (\xs -> print xs))

現在,更清楚的是分配看起來又只是局部作用域。 您大概很高興做

increment :: [Int] -> [Int]
increment = \x -> map (\x -> x+1) x

哪個在做同樣的事情。


摘要
似乎只是分配了一個新的本地范圍。 ew 如果您經常使用此功能,則會很不清楚代碼的含義。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM