[英]How do I modify a Haskell list without entering an infinite loop?
我正在Haskell中編寫一段代碼,我有一行代碼如下:
addElement :: [a] -> a -> [a]
addElement list elem = list ++ [elem]
我需要(或者至少我認為)這樣的函數,以便在我正在實現的圖形數據結構的頂點列表中添加新頂點。 現在,我可以按如下方式調用此函數
newlist = addElement oldlist elem
一切都很好。 但是,如果我寫的話
mylist = addElement mylist elem
然后在調用終止后嘗試用mylist做任何事情(確實如此),我進入一個無限循環,如果我理解正確,這是由於對Haskell的懶惰評估或某種類型( mylist
擴展為addElement (addElement ... elem) elem
如果我做對了嗎?)。
這對我的特定實現當然是不好的,因為為了我的目的,我現在每次需要向列表添加元素時都必須創建新列表。 那么如何使元素添加功能按我想要的方式工作呢?
首先, mylist = addElement mylist elem
是一個等式,它不是賦值 。 它不會被評估一次:因為Haskell是一種聲明性語言,所以你不能改變一個變量 :一旦給它一個值,它就會總是有這個值。
因此,您的等式將導致:
mylist = addElement mylist elem
= addElement (addElement mylist elem) elem
= addElement (... (addElement mylist elem) ...) elem
你明白了。
不過, 每次都不需要構建一個完整的新列表 :你可以簡單地使用(h:t)
追加到頭部 :
addElement :: [a] -> a -> [a]
addElement t h = (h:t)
這將在O(1)中構造一個“新”列表,它將舊列表重用為尾部。 如前所述,元素將被添加到前面。
解決該問題的另一種方法是使用差異列表 。 這里的列表表示為:
type DiffList a = a -> [a]
一個空列表是:
emptyDiffList :: DiffList a
emptyDiffList = \x -> x
在這種情況下,你地與差異列表:
groundDiffList :: DiffList a -> [a]
groundDiffList x = x []
並且您可以使用以下命令將元素添加到列表的末尾 :
addElement :: DiffList a -> a -> DiffList a
addElement l el = \x -> l (el:x)
然而,你總是需要為“新列表” 創建一個新變量 :你不能一下子給mylist
另一個值(你當然可以使用遞歸,但在那種情況下,那些技術上是兩個不同的變量: 調用者的mylist
,以及被調用者的mylist
)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.