我按照我在大學學習的一門課程的說明實作了一個二叉樹(注意:注意通常的二叉樹,它是一種不同的演算法,但這并不重要)在我的 set 函式set :: Eq a => SparseArray a -> Int -> a -> SparseArray a中,如果我使用它來更新一個節點,該函式將做的是制作一個值更改的樹的副本,而不是像預期的那樣更新值。
我認為這就像let ... in在 return 陳述句中使用符號一樣簡單,但程式需要能夠更改任何變數。
當然,必須有一個解決方案,就像在 Haskell 中實作串列一樣。
data Value a = Null | Value a
deriving (Eq,Read,Show)
data SparseArray a = Vacio | Nodo (Value a) (SparseArray a) (SparseArray a)
deriving (Eq,Read,Show)
set :: Eq a => SparseArray a -> Int -> a -> SparseArray a
set Vacio index x = Nodo (Value x) (Vacio) (Vacio)
set (Nodo n iz de) index x
| index < 0 = Nodo n iz de
| length(num2bin(index)) == 0 = Nodo (Value x) (iz) (de)
| head(num2bin(index)) == False && ((Nodo n iz de) == Vacio) = Nodo (Null) (setL (iz) (tail(num2bin(index))) (x)) (de)
| head(num2bin(index)) == True && ((Nodo n iz de) == Vacio) = Nodo (Null) (iz) (setL (de) (tail(num2bin(index))) (x))
| head(num2bin(index)) == False = Nodo (n) (setL (iz) (tail(num2bin(index))) (x)) (de)
| head(num2bin(index)) == True = Nodo (n) (iz) (setL (de) (tail(num2bin(index))) (x))
where setL :: Eq a => SparseArray a -> [Bool] -> a -> SparseArray a
setL Vacio index x = Nodo (Value x) (Vacio) (Vacio)
setL (Nodo n iz de) index x
| length(index) < 0 = Nodo n iz de
| length(index) == 0 = Nodo (Value x) (iz) (de)
| head(index) == False && ((Nodo n iz de) == Vacio) = Nodo (Null) (setL (iz) (tail(index)) (x)) (de)
| head(index) == True && ((Nodo n iz de) == Vacio) = Nodo (Null) (iz) (setL (de) (tail(index)) (x))
| head(index) == False = Nodo (n) (setL (iz) (tail(index)) (x)) (de)
| head(index) == True = Nodo (n) (iz) (setL (de) (tail(index)) (x))
uj5u.com熱心網友回復:
在 Haskell 中無法更改變數。這基本上是 Haskell 的全部要點。
當然,必須有一個解決方案,就像在 Haskell 中實作串列一樣。
您也不能更改串列中的值。試試吧。沒有辦法做到這一點。
let創建新變數,但不能更改變數中的值。let ... in ...不影響...! 即使你給一個新變數與另一個變數同名——這意味著在...參考新變數的代碼,但在參考之外的代碼...參考具有舊值的舊變數。
您的函式的型別簽名set表明它將樹作為引數,并回傳樹。這是有原因的:它不必回傳與其引數相同的樹。您需要回傳一棵新樹,但在可能的情況下重用舊樹的部分。每當您不想更改分支時,您可以在新樹中使用舊樹的分支。
uj5u.com熱心網友回復:
Haskell 是純函式式語言,簡而言之,所有值都是不可變的,它們是值。考慮將名稱系結到值,x = 3 意味著 x 系結到值 3,并且您無法更改該鍵。因此,Haskell 中的功能是轉換值。所以是的,在這種情況下,樹被完全“復制”并隨修改回傳,例如:
data Tree a = EmptyT | Node (Tree a) a (Tree a) deriving Show
replaceFirst x v EmptyT = EmptyT
replaceFirst x v (Node EmptyT tv EmptyT) = if (x == tv) then (Node EmptyT v EmptyT) else (Node EmptyT tv EmptyT)
replaceFirst x v (Node t1 tv EmptyT) = if (x == tv) then (Node t1 v EmptyT) else (replaceFirst x v t1)
replaceFirst x v (Node EmptyT tv t2) = if (x == tv) then (Node EmptyT v t2) else (replaceFirst x v t2)
replaceFirst x v (Node t1 tv t2) = if (x == tv) then (Node (replaceFirst x v t1) v (replaceFirst x v t2)) else (Node (replaceFirst x v t1) tv (replaceFirst x v t2))
請注意,您實際上是在創建一棵新樹,而不是實際上用新值“替換”舊值。
試試看:
t1 = Node EmptyT 4 EmptyT
t2 = Node EmptyT 5 EmptyT
t3 = Node t1 7 t2
t4 = Node t3 5 t1
main = putStrLn (show(replaceFirst 4 8 t4))
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/449979.html
上一篇:如何使用迭代設定類變數的名稱?
